+ All Categories
Home > Documents > YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API...

YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API...

Date post: 29-Jul-2020
Category:
Upload: others
View: 12 times
Download: 0 times
Share this document with a friend
285
YumaPro API Quick Start Guide YANG-Based Unified Modular Automation Tools Common API Guide Version 19.10-12
Transcript
Page 1: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

YANG-Based Unified Modular Automation Tools

Common API Guide

Version 19.10-12

Page 2: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Table of Contents1 Preface..............................................................................................................................................5

1.1 Legal Statements.........................................................................................................................51.2 Additional Resources...................................................................................................................5

1.2.1 WEB Sites......................................................................................................................................51.2.2 Mailing Lists...................................................................................................................................6

1.3 Conventions Used in this Document..............................................................................................62 YumaPro API Overview......................................................................................................................7

2.1 API Overview.............................................................................................................................72.2 Terminology................................................................................................................................9

3 YANG Data Examples......................................................................................................................103.1 Object Tree Ordering.................................................................................................................103.2 YANG Object Tree Handling Examples.......................................................................................11

3.2.1 Find Top-Level Object....................................................................................................................113.2.2 Access Module Pointer...................................................................................................................123.2.3 Match Any Object..........................................................................................................................133.2.4 Check For Child Nodes..................................................................................................................143.2.5 Find a Specific Child Node.............................................................................................................143.2.6 Find Choice or Case Child Node.....................................................................................................153.2.7 Get First Child...............................................................................................................................153.2.8 Get Next Child..............................................................................................................................163.2.9 Process All Child Nodes.................................................................................................................173.2.10 Process Ancestor Nodes................................................................................................................17

3.3 YANG Data Tree Handling Examples..........................................................................................183.3.1 Leaf Examples..............................................................................................................................183.3.2 Leaf-list Examples.........................................................................................................................203.3.3 Container Examples.......................................................................................................................213.3.4 List Examples...............................................................................................................................24

4 Database Access...............................................................................................................................274.1 Common CLI Parameters...........................................................................................................27

4.1.1 Startup Options.............................................................................................................................274.2 Database Deployment Variants...................................................................................................28

4.2.1 Local internal database...................................................................................................................284.2.2 Local internal database + NV-store Hook.........................................................................................294.2.3 Local internal database + no-NV-store..............................................................................................304.2.4 Local internal database + External Edits...........................................................................................31

4.3 DB-API Example......................................................................................................................325 Database Transaction Callbacks.........................................................................................................37

5.1 EDIT1 and EDIT2 Callbacks......................................................................................................395.1.1 Error Handling for Edit Transactions................................................................................................415.1.2 EDIT1 Callback Initialization and Cleanup.......................................................................................445.1.3 EDIT1 Callback Function Example.................................................................................................475.1.4 EDIT2 Callback Initialization and Cleanup.......................................................................................505.1.5 EDIT2 Callback Function Example.................................................................................................525.1.6 EDIT2 Utility Functions.................................................................................................................62

5.2 GET1 Callback..........................................................................................................................635.2.1 GET1 Callback Examples. Virtual data............................................................................................645.2.2 GET1 Callback Examples for Static Data.........................................................................................67

5.3 GET2 Callback..........................................................................................................................725.3.1 GET2 Callback Initialization and Cleanup........................................................................................75

Version 19.10-12 Page 2

Page 3: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.3.2 GET2 Callback Function Examples.................................................................................................775.3.3 GET2 Access Macros.....................................................................................................................945.3.4 GET2 Access Functions..................................................................................................................97

5.4 All In One GET2 callback..........................................................................................................995.4.1 All In One List Example...............................................................................................................1015.4.2 All In One Container Example.......................................................................................................1065.4.3 All In One GET2 Callbacks with XML/JSON buffers......................................................................112

5.5 User Defined Data Types..........................................................................................................1185.5.1 Callback Registration...................................................................................................................1195.5.2 typ_validate_fn_t.........................................................................................................................1215.5.3 typ_canonical_fn_t.......................................................................................................................1235.5.4 typ_compare_fn_t........................................................................................................................125

6 In-Transaction Callbacks.................................................................................................................1276.1 Callback Invocation Order........................................................................................................1306.2 Set Hook Callback...................................................................................................................132

6.2.1 Set Hook Callback Initialization and Cleanup..................................................................................1336.2.2 Set Hook Callback and add_edit() API Function Examples...............................................................1366.2.3 Set Hook Callback and add_edit_ex() API Function Examples..........................................................152

6.3 Post Set Hook Callback............................................................................................................1796.3.1 Post Set Hook Callback Initialization and Cleanup..........................................................................1806.3.2 Hooks callback interaction with EDIT2 callbacks (target=candidate).................................................1826.3.3 Hooks callback interaction with EDIT2 callbacks (target=running)....................................................183

6.4 Transaction Hook Callback.......................................................................................................1856.4.1 Transaction Hook Callback Initialization and Cleanup.....................................................................1866.4.2 Transaction Hook Callback Function Example................................................................................187

6.5 Transaction Start Callback........................................................................................................1896.5.1 Transaction Start Callback Initialization and Cleanup.......................................................................1906.5.2 Transaction Start Callback Function Examples................................................................................191

6.6 Transaction Start SA Callback...................................................................................................1936.6.1 Transaction Start SA Callback Initialization and Cleanup.................................................................1936.6.2 Transaction Start SA Callback Function Examples...........................................................................195

6.7 Transaction Complete Callback.................................................................................................1976.7.1 Transaction Complete Callback Initialization and Cleanup................................................................1986.7.2 Transaction Complete Callback Function Example..........................................................................199

6.8 Transaction Complete SA Callback...........................................................................................2006.8.1 Transaction Complete SA Callback Initialization and Cleanup..........................................................2016.8.2 Transaction Complete SA Callback Function Example.....................................................................202

6.9 Set Order Hook Callback..........................................................................................................2036.9.1 Set Order Hook Callback Initialization and Cleanup........................................................................2046.9.2 Set Order Hook Callback Function Examples..................................................................................206

6.10 Add Edit API.........................................................................................................................2096.11 Add Edit Extended API..........................................................................................................2106.12 Add Edit Maximum API.........................................................................................................2126.13 Get Data API.........................................................................................................................2146.14 Startup Hook Callback...........................................................................................................215

6.14.1 Startup Hook Callback Initialization and Cleanup..........................................................................2166.14.2 Startup Hook Callback Examples.................................................................................................218

6.15 Validate Complete Callback....................................................................................................2196.15.1 Validate Complete Callback Initialization and Cleanup...................................................................220

6.16 Apply Complete Callback.......................................................................................................222

Version 19.10-12 Page 3

Page 4: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.16.1 Apply Complete Callback Initialization and Cleanup.....................................................................2236.17 Commit Complete Callback....................................................................................................225

6.17.1 Commit Complete Callback Initialization and Cleanup...................................................................2266.18 Rollback Complete Callback...................................................................................................228

6.18.1 Rollback Complete Callback Initialization and Cleanup.................................................................2296.19 Commit Completeness Callback Function Example..................................................................2316.20 Dynamic Default Hook Callback.............................................................................................234

6.20.1 Dynamic Default Hook Callback Initialization and Cleanup............................................................2366.20.2 Dynamic Default Hook Callback Function Examples.....................................................................238

7 System Callbacks...........................................................................................................................2407.1 Candidate Reload Callback.......................................................................................................241

7.1.1 Candidate Reload Callback Example..............................................................................................2427.2 Module Load Callback.............................................................................................................243

7.2.1 Module Load Callback Initialization and Cleanup............................................................................2447.2.2 Module Load Callback Function Example......................................................................................245

7.3 Module Unload Callback..........................................................................................................2487.3.1 Module Unload Callback Initialization and Cleanup........................................................................2497.3.2 Module Unload Callback Function Example...................................................................................250

7.4 NV-Load Callback...................................................................................................................2537.4.1 NV-Load Callback Initialization and Cleanup..................................................................................2547.4.2 NV-Load Callback Function Example............................................................................................255

7.5 NV-Save Callback....................................................................................................................2567.5.1 NV-Save Callback Initialization and Cleanup..................................................................................2577.5.2 NV-Save Callback Function Example.............................................................................................258

7.6 Session Hook Callback.............................................................................................................2597.6.1 Session Hook Callback Initialization and Cleanup...........................................................................2607.6.2 Session Hook Callback Function Example......................................................................................261

7.7 Shutdown Callback..................................................................................................................2627.7.1 Shutdown Callback Initialization and Cleanup................................................................................2637.7.2 Shutdown Callback Function Example...........................................................................................264

7.8 Command Complete Callback...................................................................................................2667.8.1 Command Complete Callback Initialization and Cleanup.................................................................2687.8.2 Command Complete Callback Function Example............................................................................269

7.9 NACM External Groups Callback.............................................................................................2707.9.1 NACM External Groups Callback Initialization and Cleanup............................................................2717.9.2 NACM External Groups Callback Function Example.......................................................................272

7.10 Config Replay Callback.........................................................................................................2737.11 Periodic Timer Service...........................................................................................................274

7.11.1 Timed Config Replay Example....................................................................................................2758 RPC Operation Callbacks................................................................................................................277

8.1 RPC Callback Initialization and Cleanup...................................................................................2798.2 RPC Callback Function Examples.............................................................................................281

8.2.1 RPC Validate Callback Function....................................................................................................2818.2.2 RPC Invoke Callback Function......................................................................................................284

Version 19.10-12 Page 4

Page 5: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

1 Preface

1.1 Legal Statements

Copyright 2009 - 2012, Andy Bierman, All Rights Reserved.

Copyright 2012 - 2020, YumaWorks, Inc., All Rights Reserved.

1.2 Additional Resources

This document assumes you have successfully set up the software as described in one or both of the printed documents:

YumaPro Installation Guide

Other documentation includes:

YumaPro Quickstart Guide

YumaPro User Manual

YumaPro netconfd-pro Manual

YumaPro yangcli-pro Manual

YumaPro ypclient-pro Manual

YumaPro yangdiff-pro Manual

YumaPro yangdump-pro Manual

YumaPro Developer Manual

YumaPro yp-system API Guide

YumaPro ypgnmi Guide

YumaPro yp-show API Guide

YumaPro Yocto Linux Quickstart Guide

YumaPro yp-snmp Manual

To obtain additional support you may contact YumaWorks technical support department:

[email protected]

1.2.1 WEB Sites

• YumaWorks

◦ https://www.yumaworks.com

◦ Offers support, training, and consulting for YumaPro.

• Netconf Central

◦ http://www.netconfcentral.org/

Version 19.10-12 Page 5

Page 6: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

▪ Free information on NETCONF and YANG, tutorials, on-line YANG module validation and documentation database

• Yang Central

◦ http://www.yang-central.org

◦ Free information and tutorials on YANG, free YANG tools for download

• NETCONF Working Group Wiki Page

◦ http://trac.tools.ietf.org/wg/netconf/trac/wiki

◦ Free information on NETCONF standardization activities and NETCONF implementations

• NETCONF WG Status Page

◦ http://tools.ietf.org/wg/netconf/

◦ IETF Internet draft status for NETCONF documents

• libsmi Home Page

◦ http://www.ibr.cs.tu-bs.de/projects/libsmi/

◦ Free tools such as smidump, to convert SMIv2 to YANG

1.2.2 Mailing Lists

• NETCONF Working Group

◦ https://mailarchive.ietf.org/arch/browse/netconf/

◦ Technical issues related to the NETCONF protocol are discussed on the NETCONF WG mailing list. Refer to the instructions on https://www.ietf.org/mailman/listinfo/netconf for joining the mailing list.

• NETMOD Working Group

◦ https://datatracker.ietf.org/wg/netmod/documents/

◦ Technical issues related to the YANG language and YANG data types are discussed on the NETMOD WG mailing list. Refer to the instructions on the WEB page for joining the mailing list.

1.3 Conventions Used in this Document

The following formatting conventions are used throughout this document:

Documentation Conventions

Convention Description

--foo CLI parameter foo

<foo> XML parameter foo

foo netconfd-pro command or parameter

$FOO Environment variable FOO

$$foo netconfd-pro global variable foo

some text Example script

some text Plain text

Version 19.10-12 Page 6

Page 7: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

2 YumaPro API OverviewThis section gives a quick overview for those who want to get started with the netconfd-pro server and all the API that it provides without reading the entire manual first. It is assumed that the appropriate programs have been installed and configured correctly.

2.1 API Overview

This section describes the basic API used in the netconfd-pro server.

YumaPro tools provide numerous APIs that can be used to effectively perform desired tasks, improve efficiency, refine auto-generated code, and extend default functionality.

Version 19.10-12 Page 7

Page 8: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

YumaPro netconfd-pro API map key:

(1) Utility APIs

• Notification functions provide control over notifications. • XPATH Handling/Validation functions can be used to manipulate XPATH expressions. • Error Handling functions provide various alternative ways to record an error. • Transaction Management functions provide control on the transaction and can be invoked within, before, and

after the transaction. • Timer Service functions allow some SIL code that may need to be called at periodic intervals to check system

status, update counters, and/or send notifications. • YANG Object Tree manipulation functions let you retrieve object properties without accessing them directly. • Extension Access functions allow to manipulate with custom YANG extensions. • YANG Data Tree manipulation functions provide access functions to the data nodes.

(2) Server Instrumentation Library (SIL) Utility functions provide control on SIL libraries and allows them to be used more efficiently.

(3) YControl and DB-API Interface functions provide control on subsystem and DB-API interfaces.

(4) System Callback functions allow the creation and use of general system SIL libraries.

(5) Database Access functions allow validation, manipulation, and management of your database.

(6) Access Control functions allow configuration and enforcement of a vendor specific access control model (ACM).

(7) SYSLOG and Log functions allow customized logging preferences.

YumaPro provides the following APIs:

• Transaction Management functions that provide control on the transaction and can be invoked within, before, and after the transaction.

• YANG Object Tree manipulation functions, so that object properties do not have to be accessed directly.

• YANG Data Tree manipulation functions provide access functions to the data nodes.

• Error Handling functions provide various alternative ways to record an error.

• Notification functions provide control on notifications.

• XPATH Handling/Validation functions can be used to manipulate XPATH expressions.

• Extension Access functions allow to manipulate with custom YANG extensions.

• Timer Service functions allow some SIL code that may need to be called at periodic intervals to check system status, update counters, and/or perhaps send notifications.

• SIL Utility functions provide control on SIL libraries and allows to use them more efficiently.

• System Callback functions allow to creating and use the general system SIL library.

• Access Control functions allow to configure and enforce ACM.

• SYSLOG and Log functions allow to customize logging.

• Database Access functions allow to validate, manipulate, and manage database.

• YCONTROL Interface functions provide communication service between sub-agents and the main server.

• DB-API Interface provide database interface functions to edit the internal database from another internal process.

YUMAWORKS RESERVES THE RIGHT TO CHANGE INTERNAL DATA STRUCTURES AT ANY TIME WITHOUT NOTICE! API FUNCTIONS ARE STABLE, NOT DATA STRUCTURES!

Version 19.10-12 Page 8

Page 9: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

2.2 Terminology

Data Tree The 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.

Object Tree The Object Tree is a tree representation of all the YANG module RPC, data definition, and notification statements. It starts with a Root container. This is defined with a YANG container statement which has an ncx:root extension statement within it. The <config> parameter within the <edit-config> operation is an example of an object node which is treated as a Root container. Each configuration database maintained by the server (e.g., <candidate> and <running>) has a Root container value node as its top-level object.

Root container The Root container is defined with a YANG container statement which has an ncx:root extension statement within it. The Root container does not have any child nodes defined in it within the YANG file. However, the YumaPro tools will treat this special container as if any top-level YANG data node is allowed to be a child node of the Root container type.

Version 19.10-12 Page 9

Page 10: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3 YANG Data ExamplesThis section describes the basic design and demonstrates and exemplifies how to handle the YANG Object Tree and the corresponding Data Tree that represents instances of various object nodes that the client or the server can create.

The Object Tree is a tree representation of all the YANG module RPC, data definition, and notification statements. It startswith a Root container. This is defined with a YANG container statement which has an ncx:root extension statement within it. The <config> parameter within the <edit-config> operation is an example of an object node which is treated as a Root container. Each configuration database maintained by the server (e.g., <candidate> and <running>) has a Root container value node as its top-level object.

A Root container does not have any child nodes defined in it within the YANG file. However, the YumaPro tools will treat this special container as if any top-level YANG data node is allowed to be a child node of the Root container type.

The 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.

3.1 Object Tree Ordering

Top-Level Data Nodes are derived from:

• data-def-stmt

• rpc-stmt

• notification-stmt

The YANG object tree is maintained in “schema order” wherever that is defined.

• Top-Level Data Nodes:

◦ These nodes are sorted:

▪ Primary Key: local-name

▪ Secondary Key: module-name

◦ The top-level YANG objects from all loaded modules are present in the object tree (except if removed by status=obsolete or deviation=not-supported)

• Child Data Nodes, RPC and Notification Nodes

◦ Child nodes defined in the current module are in schema order (order they appear in the YANG module

◦ Augmenting child nodes are in no defined order. They will be after all the real child nodes and the order may change depending on how the augmenting modules are loaded.

▪ DO NOT DEPEND ON THE ORDER OF AUGMENTING DATA NODES

Version 19.10-12 Page 10

Page 11: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3.2 YANG Object Tree Handling Examples

In this section we will go through examples on how to utilize different type of the Object Trees, what API functions can be used for specific purpose, and when you should consider one API function to another.

Let us go through the most prominent Object Tree handling examples, that are often used in SIL callbacks.

There are various API functions that you can use to locate desired objects, they differ widely by available information that you have prior the search and by desired search precision.

3.2.1 Find Top-Level Object

Assume you know the name of the target object and your goal is to obtain its object template. Assume the object is a top level object in the YANG module, in this case you cannot use obj_find_child or analogous API function that are using parent object to locate a child object. In this scenario you have two options, use module structure to locate desired objects or search through all the modules and try to match the object name string.

If you know the module where the target object is located, the following retrieval function can be used:

...

/* get the top object node */ obj_template_t *topobj = obj_find_template_top(mod,

module_name, object_name); if (!topobj) { res = ERR_NCX_DEF_NOT_FOUND; }

...

Version 19.10-12 Page 11

Page 12: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3.2.2 Access Module Pointer

If you are developing code in the SIL code, the module usually is getting loaded to the server during the Initialization Phase1 before the startup configuration is loaded into the running configuration database, and before the running configuration is loaded. The following code illustrates how the module pointer can be obtained during the module load procedure:

/******************************************************************** * FUNCTION init_function* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t init_function (const xmlChar *modname, const xmlChar *revision) { ...

res = ncxmod_load_module(modname, revision, agt_get_savedevQ(), mod); if (res != NO_ERR) { return res; }

...}

After we load the module and have the module pointer, we can utilize it to locate top level objects in the module.

Alternatively, if the module already loaded and you want to locate the module in order to use it later to search for object templates you may use the following API function:

...

ncx_module_t *mod = ncx_find_module(modname, revision); if (mod == NULL) { res = ERR_NCX_DEF_NOT_FOUND; }

...

Version 19.10-12 Page 12

Page 13: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3.2.3 Match Any Object

The second option to locate a top level object is to search through all the modules and try to match the object name string. The following API functions illustrate how to locate the top level object based on module name:

...

obj_template_t *topobj = ncx_match_any_object(object_name, NCX_MATCH_FIRST, alt_names, &res); ...

In the above example, NCX_MATCH_FIRST parameter dictates the API function to stop search on the first match. Alternatively, the parameter can be changed to the following options:

Match mode description

NCX_MATCH_EXACT Try a case-sensitive exact-length match

NCX_MATCH_EXACT_NOCASE Try a case-insensitive exact-length match

NCX_MATCH_ONE Try a case-sensitive partial-name match

NCX_MATCH_ONE_NOCASE Try a case-insensitive partial-name match

NCX_MATCH_FIRST Try a case-sensitive first match

NCX_MATCH_FIRST_NOCASE Try a case-insensitive first match

The alt_names parameter dictates if alternative names should be checked in addition to the YANG node names. If set to TRUE the check will be applied; if set to FALSE the check will be ignored.

The *res parameter may be set to ERR_NCX_MULTIPLE_MATCHES in case there are multiple matching objects available. In this case the function will not return any of the object templates. If you want to search with the highest precision for a specific object you should consider NCX_MATCH_EXACT value and set alt_names to FALSE.

Alternatively, you can use the following extended version of the previous API function:

... obj_template_t *topobj = ncx_match_any_object_ex(modname, object_name, dataonly, NCX_MATCH_EXACT, alt_names, &res); ...

Version 19.10-12 Page 13

Page 14: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

In the above example, the module name is optional; however it is recommended. If it is present the API function will searchonly within specified module and will not try to search through all the modules.

The dataonly parameter specifies whether the search function should try to match only data nodes or not. Set to TRUE if it should.

The *res parameter may be set to ERR_NCX_MULTIPLE_MATCHES in case there are multiple matching objects available. In this case the function will not return any of the object templates. If you want to search with the highest precision for a specific object you should consider NCX_MATCH_EXACT value and set alt_names to FALSE.

3.2.4 Check For Child Nodes

Now, since we know the top level object we can locate any children objects of the current top level object. However, only ifthe current object has and may have children.

In order to verify that the current object has any available children you may use the following API function:

...

boolean has_children =obj_has_children(topobj);

...

If there are any accessible nodes within the object the function returns TRUE.

3.2.5 Find a Specific Child Node

The following example code illustrates how to locate a specific child object of the current top level object. The following API function checks for accessible names only. That means child nodes of choice, case will be present instead of the choice name or case name:

... /* get the child obj template */ obj_template_t *child_obj = obj_find_child(topobj, modname, objname);

...

Version 19.10-12 Page 14

Page 15: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3.2.6 Find Choice or Case Child Node

In case you want to locate choice or case objects as well as other accessible names you may consider to use the following API function. This function checks not only for accessible names. That means the choice name or case name will be preferred instead of their child nodes:

... /* get the child obj template */ obj_template_t *child_obj = obj_find_child_choice_case(topobj, modname, objname);

...

Alternatively, you can use the following extended version of the previous API functions:

...

/* get the child obj template */ obj_template_t *child_obj = obj_find_child_ex(topobj, modname, objname, NCX_MATCH_FIRST, alt_names, dataonly, &res); ...

3.2.7 Get First Child

In addition to the find_child family API functions, you may consider to use get_child API functions. The main difference is that find functions are trying to match desired object, but get functions merely get the first, next, last, etc objects.

To exemplify, if you want to get the first child object of the current object, the following API function can be used. Note, that this function skips over augments and uses:

...

obj_template_t *first_obj = obj_first_child(topobj);

...

Version 19.10-12 Page 15

Page 16: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Similarly, the following API function can be used to locate the first terminal object. Note, that this function also skips over augments and uses:

...

obj_template_t *first_obj = obj_first_terminal_child(topobj);

...

3.2.8 Get Next Child

In order to get the next, the last, parent or previous child object or the terminal child object the following API functions can be used:

...

obj_template_t *next_obj = obj_next_child(first_obj);

obj_template_t *next_obj = obj_next_terminal_child(first_obj);

obj_template_t *prev_obj = obj_previous_child(next_obj);

obj_template_t *last_obj = obj_last_child(topobj);

obj_template_t *topobj = obj_get_parent(next_obj);

...

Version 19.10-12 Page 16

Page 17: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3.2.9 Process All Child Nodes

To summarize previous list of API functions, you may construct the following loop to apply custom actions for desired children objects:

...

/* check all the child nodes */ obj_template_t *chobj = obj_first_child(obj); for (; chobj; chobj = obj_next_child(chobj)) {

const xmlChar *modname = obj_get_mod_name(chobj);const xmlChar *objname = obj_get_name(chobj);

/* process objects here */

}

...

3.2.10 Process Ancestor Nodes

In order to loop through ancestor entries and process them as required, the following code may be used:

...

/* go through the ancestor entries and process them as needed */ obj_template_t *testobj = obj_get_parent(chobj); while (testobj) {

/* process parent objects here */

testobj = obj_get_parent(testobj); if (testobj && obj_is_root(testobj)) { testobj = NULL; } }

...

The obj_is_root API function signals when to stop. It is also possible to have a NULL pointer returned. That indicates you reached the top Root container. This container should NOT be modified, accessed or changed in any manner.

Version 19.10-12 Page 17

Page 18: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

3.3 YANG Data Tree Handling Examples

In this section we will go through examples on how to utilize different type of the Data Trees, what API functions can be used for specific purpose, and when you should consider one API function to another.

Let us go through the most prominent Data Tree handling examples, that are often used in SIL callbacks.

There are various API functions that you can use to manipulate with desired Data node, they differ widely the operation thatyou need to perform. Let us go through simple examples that will illustrate how to manage different YANG node types.

3.3.1 Leaf Examples

The following examples illustrates how to construct a simple leaf data node.

There are multiple ways to construct leaf node depending on what information you have before the construction and what data type is the node.

The most common and generic API function to construct the data node that does not required to know the type of the node is demonstrated below. However, you have to find the object template prior the construction:

...

obj_template_t *leafobj = obj_find_child(parentobj,

modname, objname);

if (!leafobj) { /* 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 */ val_value_t *any_type_leaf = val_make_simval_obj(leafobj, (const xmlChar *)"8", &res); ...

The most beneficial part of this API function is that you do NOT have to investigate the type of the node before the construction.

However, If you know the type of the node and want to construct the value based on the type, the following example demonstrates how to accomplish this goal. In this example we are constructing “string” type data node:

...

/* construct a sting type leaf */ val_value_t *string_leaf = agt_make_leaf(parentobj, leafname, (const xmlChar *)"example value",

Version 19.10-12 Page 18

Page 19: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

&res); ...

In the example code above, if the PARENTOBJ is a leaf or leaf-list then it will be used directly instead of checking for a child node.

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

...

/* construct a uint32 type leaf */ val_value_t *string_leaf = agt_make_uint_leaf(parentobj, leafname, (uint32)32, &res);

/* construct a uint32 type leaf */ val_value_t *value = agt_make_int_leaf(parentobj, leafname, (int32)32, &res);

/* construct a uint64 type leaf */ val_value_t *value = agt_make_uint64_leaf(parentobj, leafname, (uint64)64, &res);

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

...

In order to construct data node with boolean type, the following API function can be used. The BOOLVAL value is getting set to TRUE is the value of this node should be TRUE:

...

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

...

Version 19.10-12 Page 19

Page 20: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

In order to construct data node with empty type, the following API function can be used. The BOOLVAL value is ignored by this API function:

...

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

...

3.3.2 Leaf-list Examples

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

The leaf-list nodes can be constructed the same way as regular leaf nodes. However, there might be multiple instances, siblings of the same leaf-list node in the Data Tree.

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

...

/* construct 3 leaf-list entries */ 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_value) { return res; }

val_value_t *leaflist_value3 = val_make_simval_obj(leaflist_obj, (const xmlChar *)"80", &res); if (!leaflist_value) { 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:

Version 19.10-12 Page 20

Page 21: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

...

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. The next section will describe this construction in more details.

3.3.3 Container Examples

The following examples illustrates 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);

...

Version 19.10-12 Page 21

Page 22: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

On the other hand, if the container is a top level container, and you are constructing it in order to use as a static or virtual data within running datastore. If the container represents operational data, the following example can be used:

...

cfg_template_t *runningcfg = cfg_get_config_id(NCX_CFGID_RUNNING); if (!runningcfg || !runningcfg->root) { return ERR_NCX_DEF_NOT_FOUND; }

/* get the top object node */ obj_template_t *topobj = obj_find_template_top(mod,

module_name, object_name); if (!topobj) {

return ERR_NCX_DEF_NOT_FOUND; }

/* construct top level container */ val_value_t *cont_value = val_new_value(); if (!cont_value) { return ERR_INTERNAL_MEM; } val_init_from_template(cont_value, topobj);

/* handing off the malloced memory here */ res = val_child_add(cont_value, runningcfg->root); if (res != NO_ERR) {

val_free_value(cont_value); return res; }

...

As a result of these two examples, we will have an empty container with no any children. In order to add a child to the container, the following example that creates multiple leaf-list entries and adds them into parent container can be used:

...

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);

Version 19.10-12 Page 22

Page 23: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

return res; } }

...

In order to construct nested containers, the same steps should be applied twice, as illustrated below:

...

cfg_template_t *runningcfg = cfg_get_config_id(NCX_CFGID_RUNNING); if (!runningcfg || !runningcfg->root) { return ERR_NCX_DEF_NOT_FOUND; }

/* get the top object node */ obj_template_t *topobj = obj_find_template_top(mod,

module_name, object_name); if (!topobj) {

return ERR_NCX_DEF_NOT_FOUND; }

/* construct top level container */ val_value_t *cont_value = val_new_value(); if (!cont_value) { return ERR_INTERNAL_MEM; } val_init_from_template(cont_value, topobj);

/* handing off the malloced memory here */ status_t res = val_child_add(cont_value, runningcfg→root); if (res != NO_ERR) { val_free_value(cont_value); return res; }

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

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

res = val_child_add(next_cont_value, cont_value); if (res != NO_ERR) {

Version 19.10-12 Page 23

Page 24: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_free_value(next_cont_value); val_free_value(cont_value); return res; }

...

3.3.4 List Examples

The following examples illustrates how to construct a list data node.

The list nodes have several limitations and special handling nuances. For following list summarize the most important:

• NETCONF does not require entries to be sorted by index. It only requires the order to be maintained if “ordered-byuser” is configured in the YANG module. The server will maintain the order or instances given in the <edit-config> or startup or other sources. It will maintain YANG schema order so the objects will be returned in the correct order according to the YANG module.

• val_gen_index_chain MUST be called after all the index leafs have been added to the list. This can be done before or after any additional child nodes are added to the list.

• The index (key) nodes should be added first, before any other nodes are added.

There are multiple variants of val_child_add. Sometimes the value is only created so it can be output in XML or JSON, and not to be stored in the database. The API functions in val_child should be used instead of val.c. The val.c API functionsstill works, but the new functions should be used in new code. The new functions can fail with an error, so it is important to check the return value in server code. The yangcli-pro and compiler programs will use val_child_add_force by default, since they do not store the data nodes in a database.

Function Description

val_child_add Replaces val_add_child and val_add_child_sorted

val_child_add_force Allows AVL tree insertion to be skipped for duplicates or incomplete list entries

val_child_insert Replaces val_insert_child

The following example illustrates how to construct the list data node with multiple children:

/******************************************************************** * FUNCTION create_list_entry3 * * Make a list entry based on the key * * INPUTS: * res = return status * * RETURNS: * val_value_t of listval entry if no error

Version 19.10-12 Page 24

Page 25: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* else NULL * *********************************************************************/ 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);

/* make key leaf entry */ val_value_t *child = agt_make_int_leaf(list_obj, keyname, key, res); if (!child) { val_free_value(list_value); return NULL; } *res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); val_free_value(list_value); return NULL; }

/* make an extra leaf entry */ child = agt_make_uint_leaf(list_obj, (const xmlChar *)”my-other-leaf”, (uint32)32, res); if (!child) { val_free_value(list_value); return NULL; } *res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); 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) {

Version 19.10-12 Page 25

Page 26: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_free_value(list_value); return NULL; } return list_value;

} /* create_list_entry3 */

This above function is an example function and can be changed according to the required goal. By using this function, we create one list entry that we can now add to the parent or repeat the same steps but with different key value in order to generate another list entry. The following example illustrates how to generate multiple list entries using the sample function above and add them to parent container value:

...

/* malloced and construct list values */ 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; } }

...

As a result we generated container with 5 list entries.

Version 19.10-12 Page 26

Page 27: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

4 Database AccessThis document describes the configuration and deployment options for the configuration database used by the netconfd-pro server.

Information included:

• Database related CLI parameters

• Deployment Variants

◦ Use-Case description

◦ System integration description

◦ Related Callback APIs

4.1 Common CLI Parameters

4.1.1 Startup Options

There are 3 startup parameter variants, using the YANG 'start' choice statement.

• choice of 3 leafs:

◦ --startup

◦ --factory-startup

◦ --no-startup

The --startup=filespec CLI parameter can be used to specify the NV-storage file. The default filespec is $HOME/.yumapro/startup-cfg.xml

The parameter --factory-startup can be used to load an empty configuration instead of the stored configuration. If the default configuration is used (startup-cfg.xml) then it is reset to factory default values.

The parameter --no-startup can be used to load an empty configuration instead of the stored configuration. The default configuration (startup-cfg.xml) is not affected by this parameter.

Version 19.10-12 Page 27

Page 28: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

4.2 Database Deployment Variants

There are many ways to configure and build the server for storing and retrieving datastore contents.

• Local internal database: configuration in memory and NV-storage in netconfd-pro owned XML file

• Local internal database + NV-store hook: configuration in memory and NV-storage via callback functions, and transferred to/from the server as an XML file

• Local internal database + no-NV-store: configuration in memory and NV-storage is managed by the yp-system and/or SIL code. The server will not attempt to load or store the configuration to non-volatile storage

• Local internal database + external edits: your external process communicates with the netconfd-pro process to initiate external edits (e.g., initiated from legacy CLI or internal database)

4.2.1 Local internal database

This is the default database configuration and provides complete management of all database storage and management. No extra APIs or CLI parameters are required.

Configuration properties:

• Tree-based data structures in memory for run-time transaction processing

• This is the canonical database

• There is no other database

• The non-volatile load and store is done by netconfd-pro using the --startup filespec to store the configuration

• The file is encoded as an XML instance document containing 1 element named 'data'

• No YANG default leafs are stored in this file

Version 19.10-12 Page 28

Page 29: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

4.2.2 Local internal database + NV-store Hook

This database variant allows the vendor/system code to manage the non-volatile configuration. The system control is constrained to the replacement of the functions that load and store the configuration file.

This variant requires use of the NV-store APIs (described in the Database Transaction Callbacks section of this document).

Configuration properties:

• Tree-based data structures in memory for run-time transaction processing

• This is the canonical database

• There is no other database

• The non-volatile load and store is done by netconfd-pro via user callback functions.

• The NV-store callback functions manage the actual non-volatile representation and storage.

• The NV-Store callback transfers the configuration to/from netconfd-pro as an XML file

• YANG default leafs will be treated as explicitly set if contained in the transfer file

Version 19.10-12 Page 29

Page 30: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

4.2.3 Local internal database + no-NV-store

This variant allows either a simple deployment that does not support non-volatile storage of configuration or

a more flexible system-managed non-volatile storage design, using multiple server APIs.

This variant requires that the CLI parameter --no-nvstore be set to 'false'.

The --startup CLI parameter is ignored if --no-nvstore is used.

Various initialization callback APIs and transaction APIs can be used to load and save the non-volatile storage

Configuration properties:

• Tree-based data structures in memory for run-time transaction processing

• This is the canonical database

• There is no other database

• The non-volatile load and store is done by netconfd-pro via various user callback functions.

• The internal NV-store and NV-store callback functions are not used

• The yp-system library or individual SIL libraries can be used to initialize and fill the empty database with configuration and operational data nodes

• Transaction hooks can be used to save the running configuration at run-time if any client edit transactions are processed by the server

Version 19.10-12 Page 30

Page 31: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

4.2.4 Local internal database + External Edits

This database variant allows an external process to initiate database edits, that are processed by the server as user or system edits.

The DB-API functions described in the next section can be used by the subsystem to edit the server configuration database.

This variant can be used with other variants for processing non-volatile storage. This variant is used to co-exist with a legacy or canonical database owned by the system.

Configuration properties:

• Tree-based data structures in memory for run-time transaction processing

• This may or may not be the canonical database, depending on the non-volatile storage options.

• There may be another database in the system

• The server uses its copy in memory as the complete database

• The DB-API “send_edit” and “send_edit_ex” API functions can be used to transfer configuration from the system to netconfd-pro.

• Data is transferred in XML

• Error responses are sent by the server if an edit is not accepted.

• An error will be returned if a client is already in the process of editing the database

• The db-api-app application is installed in /usr/share/yumapro/src/db-api-app by default, and includes some examples of initializing the DB-API service and sending edits to the server

Version 19.10-12 Page 31

Page 32: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

4.3 DB-API Example

The DB-API subsystem allows an external process on the same system as netconfd-pro to send database edits to the server.

• db_api_register_service

• db_api_service_ready

• db_api_send_edit

• db_api_send_edit_ex

• db_api_send_edit_full

• db_api_check_edit

extern status_t db_api_register_service (void);

extern boolean db_api_service_ready (void);

extern status_t db_api_send_edit (const xmlChar *edit_target, const xmlChar *edit_operation, const xmlChar *edit_xml_value);

extern status_t db_api_send_edit_ex (const xmlChar *edit_target, const xmlChar *edit_operation, const xmlChar *edit_xml_value, const xmlChar *patch_id_str, boolean system_edit);

/********************************************************************* FUNCTION db_api_send_edit_full** Create a YANG Patch edit request and send it to the DB-API service* on the main server.** The content should represent the intended target resource* as specified in YANG-API (NOT RESTCONF)* Only the data resource identifier is provided, not the* API wrapper identifiers (so this can change when RESTCONF is supported)* Example leaf:** edit_target == /interfaces/interface/eth0/mtu* edit_value == "<mtu>9000</mtu>* edit_operation == "merge"* patch_id_str == "my-patch-x01'* system_edit == true** Example list:** edit_operation == <operation string>

Version 19.10-12 Page 32

Page 33: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* "create"* "delete"* "insert"* "merge"* "move"* "replace"* "remove"** edit_target == /interfaces/interface/eth0/ipv4* edit_value == "<ipv4>* <enabled>true</enabled><* <forwarding>true</forwarding>* <address>204.102.10.4</address>* <prefix-length>24</prefix-length>* </ipv4>"** INPUTS:* edit_target == target resource (YANG-API path expression)* edit_operation == edit operation (create merge replace delete remove)* edit_xml_value == XML payload in string form, whitespace allowed* MAY BE NULL if no value required (delete remove))* patch_id_str == string to use as the patch ID* == NULL to use the default patch-id field* system_edit == TRUE if this edit is from the system and should* bypass access control enforcement* == FALSE if this edit is from a user and should not* bypass access control enforcement* insert_point is a string like the target except a different instance* of the same list of leaf-list; only for before, after* insert_where == <insert enum string>* "before"* "after"* "first"* "last"* RETURNS:* status*********************************************************************/extern status_t db_api_send_edit_full (const xmlChar *edit_target, const xmlChar *edit_operation, const xmlChar *edit_xml_value, const xmlChar *patch_id_str, boolean system_edit, const xmlChar *insert_point, const xmlChar *insert_where);

/********************************************************************* FUNCTION db_api_check_edit** Check on the status of an edit in progress* RETURNS:* status:** ERR_NCX_NOT_FOUND if final status and no message* response is pending* ERR_NCX_SKIPPED if final status is not known yet* NO_ERR if there is a last-completed operation that* completed with an OK response* <errcode> if there is a last-completed operation that* completed with an ERROR response*********************************************************************/extern status_t

Version 19.10-12 Page 33

Page 34: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

db_api_check_edit (void);

Example db-api-app send_edit from /db-api-app/main.c

/********************************************************************* FUNCTION send_test_edit** This is an example send edit function.* The module ietf-interfaces needs to be loaded for this to work*********************************************************************/static void send_test_edit (void){ /* mef-cfm test */ const xmlChar *path_str = (const xmlChar *)"/maintenance-domain/mdTest"; const xmlChar *operation_str = (const xmlChar *)"merge"; const xmlChar *value_str = (const xmlChar *) "<cfm:maintenance-domain xmlns:cfm='http://metroethernetforum.org/" "ns/yang/mef-cfm'><cfm:id>mdTest</cfm:id><cfm:name-type>character" "-string</cfm:name-type><cfm:name>mdTestName</cfm:name><cfm:md-le" "vel>4</cfm:md-level><cfm:mhf-creation>none</cfm:mhf-creation>" "<cfm:id-permission>none</cfm:id-permission></cfm:maintenance" "-domain>";

const xmlChar *patch_id_str = NULL; boolean system_edit = FALSE; status_t res = db_api_send_edit_ex(path_str, operation_str, value_str, patch_id_str, system_edit); if (res != NO_ERR) { log_error("\nSend test edit failed %s %s = %s (%s)\n", operation_str, path_str, value_str, get_error_string(res)); } else if (LOGDEBUG) { log_debug("\nSend test edit OK %s %s = %s\n", operation_str, path_str, value_str); }

} /* send_test_edit */

/********************************************************************* FUNCTION main** This is an example main function.** RETURNS:* 0 if NO_ERR* status code if error connecting or logging into ncxserver*********************************************************************/int main (int argc, char **argv)

Version 19.10-12 Page 34

Page 35: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

{#ifdef MEMORY_DEBUG mtrace();#endif

/* 1) setup yumapro messaging service profile */ status_t res = ycontrol_init(argc, argv, (const xmlChar *)"subsys1");

/* 2) register services with the control layer */ if (res == NO_ERR) { res = db_api_register_service(); }

/* 3) do 2nd stage init of the control manager (connect to server) */ if (res == NO_ERR) { res = ycontrol_init2(); }

useconds_t usleep_val = 100000; // 100K micro-sec == 1/10 sec boolean done = FALSE;

/* 4) call ycontrol_check_io periodically from the main program * control loop */#ifdef DB_API_APP_DEBUG int id = 0;#endif // DB_API_APP_DEBUG

boolean test_done = FALSE;

while (!done && res == NO_ERR) {#ifdef DB_API_APP_DEBUG if (LOGDEBUG3) { log_debug3("\ndb-api-app: checking ycontrol IO %d", id++); }#endif // DB_API_APP_DEBUG

res = ycontrol_check_io();

if (ycontrol_shutdown_now()) { // YControl has received a <shutdown-event> // from the server subsystem is no longer active // could ignore or shut down YControl IO loop done = TRUE; }

// Using sleep to represent other program work; remove for real if (!done && res == NO_ERR) { (void)usleep(usleep_val); }

if (db_api_service_ready() && !test_done) { send_test_edit(); test_done = TRUE; }

}

/* 5) cleanup the control layer before exit */ ycontrol_cleanup();

#ifdef MEMORY_DEBUG

Version 19.10-12 Page 35

Page 36: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

muntrace();#endif

return (int)res;

} /* main */

Version 19.10-12 Page 36

Page 37: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5 Database Transaction CallbacksYumaPro provides pre-transaction, in-transaction and post-transaction APIs to manage behavior of a database edit transaction, such as its functionality, order, etc. This section illustrates how to utilize transaction callbacks, highlighting some relevant use cases in detail.

YANG can model state data, as well as configuration data, based on the "config" statement. When a node is tagged with "config false", its sub-hierarchy is flagged as state data, to be reported using NETCONF's <get> operation, not the <get-config> operation. When a node has no tag or tagged with “config true”, its sub-hierarchy is flagged as configuration data.

Consider this simplified, but functional, example.

...

container interfaces { list interface { key "name";

leaf name { type string; } leaf-list untagged-ports { type string; } leaf speed { type enumeration { enum 10m; enum 100m; enum auto; } } leaf observed-speed { config false; type uint32; } } }

...

leaf version { config false; type string; }

In this example, three leafs are defined for each interface, a configured “speed” and “untagged-ports” and a non-configurable “observed-speed”. The “speed” and “untagged-ports” is configuration, so it can be returned with NETCONF <get-config> operations and they can be manipulated using <edit-config>. Note that the “observed-speed” is not configuration and it cannot be manipulated using <edit-config>.

This differentiation is critical and based on it an appropriate callback should be used. For the configuration data there should be EDIT-like callbacks registered. However, for the state data, GET-like callbacks should be registered.

Version 19.10-12 Page 37

Page 38: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The following transaction management APIs are used to manage an object that is being edited or retrieved. They are used toprovide a callback sub-mode for a specific named object.

API Description

EDIT-1 callback agt_cb_fn_t: First generation callbacks are generated by yangdump-sdk using node-based APIs. An edit function is generated for every node, including terminal nodes (leaf, leaf-list, anyxml). The GET1 API is assumed for read-only data, so code to generate virtual read-only nodes (Make Read Only MRO) is included in an EDIT1 callback. This is the default in yangdump-sdk and make_sil_* scripts.

EDIT-2 callback agt_cb_fn_t: Second generation callbacks are generated by yangdump-sdk using container or list-based APIs. An edit function is generated for “parent” list and container nodes only. The terminal child nodes are handledby this callback. Each nested container or list has its own callback. This is generated in yangdump-sdk or make_sil_* scripts using the –sil-edit2 parameter. The same callback function signature as EDIT1 is used, but the registration function and procedure is different.

GET-1 callback getcb_fn_t: Used for <get> and <get-config> operations. GET1 requires an actual data node in the data tree for each instance that exists. A data node with a GET1 callback function is called a 'virtual nodes'. It is usually createdin SIL code for operational data. Only supports internal GET callback

GET-2 callback getcb_fn2_t: Used for the <get> operation. There is 1 GET2 callback for the object, not each instance in the data tree. GET, GETNEXT, and GETBULK operations are supported. Optional parameters allow subtree/XPath filtering to be passed to the GET2 callback for pruning.

Version 19.10-12 Page 38

Page 39: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1 EDIT1 and EDIT2 Callbacks

The following sections illustrates how to utilize the EDIT1 and EDIT2 callbacks in examples.

The server supports 2 modes of database editing callbacks. The original mode (EDIT1) is designed to invoke data node callbacks at the leaf level. This means that each altered leaf will cause a separate SIL callback. If no leaf callbacks are present, then the parent node will be invoked multiple times.

The EDIT2 mode is “list-based” or “container-based” instead. The following key aspects define EDIT2 callbacks:

• In this mode there are no SIL callback functions expected for terminal nodes (leaf, leaf-list, anyxml).

• The SIL callback for a container or list will be invoked, even if only child terminal nodes are being changed.

• The parent SIL callback will be invoked only once (per phase) if multiple child nodes are being altered at once

• The parent node for such an edit is flagged in the “undo” record as a special “edit2_merge”. The edit operation willbe “OP_EDITOP_MERGE”, but the parent node is not being changed

• The special “edit2_merge” type of edit will have a queue of child_undo records containing info on the child edits. For example, 1 leaf could be created, another leaf modified, and a third leaf deleted, all in the same edit request. The child_undo records provide the edit operation and values being changed.

The following function template definition is used for EDIT1 and EDIT2 callback functions:

/* Typedef of the EDIT1/2 callback functions */typedef status_t (*agt_cb_fn_t) (ses_cb_t *scb,

rpc_msg_t *msg, agt_cbtyp_t cbtyp, op_editop_t editop, val_value_t *newval, val_value_t *curval);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per object

• File: agt_cb.h

• Template: agt_cb_fn_t

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ cbtyp == reason for the callback

▪ editop == edit operation enumeration for the node being edited

▪ newval == object holding the proposed changes to apply to the current config, depending on the editop value.

Version 19.10-12 Page 39

Page 40: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

▪ curval == current values from the <running> or <candidate> configuration, if any. Could be NULL for create and other operations.

◦ Returns: status_tStatus of the callback function execution

• Register: agt_cb_register_callback / agt_cb_register_edit2_callback

• Unregister: agt_cb_unregister_callbacks

Where, the scb parameter represents a session control block structure that is defined in the netconf/src/ncx/ses.h. This control block is primarily used for error reporting, as described in the example section later. However, can be used for more advanced actions. It provides access to the session specific information, such as current message input/output encoding, current session ID information, current protocol information, user name information, peer address information, etc. Note, almost all the fields in this structure should NOT be changed and accessed directly. This control block ideally should be used only for getting more information about the current session, not for alteration of any of its fields.

The msg parameter represents the NETCONF Server and Client RPC Request/Reply Message Handler control block that is defined in the netconf/src/ncx/rpc.h. Similarly to SCB, this control block is primarily used for error reporting, as described in the example section later. The fields of this control block should NOT be access and changed for other purposes.

The cbtype parameter represents an enumeration structure of the different server EDIT callback types that is defined in the netconf/src/agt/agt.h. This control block specifies what Phase is in the process, Validation, Apply, or Commit/Rollback, as described in the example section later.

The editop parameter represents an enumeration structure of the NETCONF edit-config operation types that is defined in the netconf/src/ncx/op.h. This control block specifies what operation is in the process, merge, replace, delete, or other, as described in the example section later.

The newval and curval parameters represent data nodes that are being edited. The example section demonstrates how they can be utilized.

Version 19.10-12 Page 40

Page 41: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1.1 Error Handling for Edit Transactions

NOTE:

Do not use SET_ERROR() macro to return normal errors. This macro will cause “assert()” to be invoked, halting programexecution. The macro defined in netconf/src/ncx/status.h and it is for flagging internal errors only. This macro must not beused for normal errors.

The agt_record_error function is one of the main error handling functions used in SIL code.

If a specific error is not recorded by SIL code when an EDIT1 or EDIT2 callback is invoked. then the server will record a generic error, based on the 'status_t' returned by the SIL code.

In the following part of the above code example we are trying to record an error if some of the previous steps fail. This errorwill be sent to the client side signaling that the <edit-config> operation failed to complete.

/********************************************************************* FUNCTION agt_record_error** Generate an rpc_err_rec_t and save it in the msg** INPUTS:* scb == session control block * == NULL and no stats will be recorded* msghdr == XML msg header with error Q* == NULL, no errors will be recorded!* layer == netconf layer error occured <error-type>* res == internal error code <error-app-tag>* xmlnode == XML node causing error <bad-element> <error-path> * == NULL if not available * parmtyp == type of node in 'error_info'* error_info == error data, specific to 'res' <error-info>* == NULL if not available (then nodetyp ignored)* nodetyp == type of node in 'error_path'* error_path == internal data node with the error <error-path>* == NULL if not available or not used * OUTPUTS:* errQ has error message added if no malloc errors* scb->stats may be updated if scb non-NULL** RETURNS:* none*********************************************************************/extern void agt_record_error (ses_cb_t *scb,

xml_msg_hdr_t *msghdr, ncx_layer_t layer, status_t res, const xml_node_t *xmlnode, ncx_node_t parmtyp, const void *error_info, ncx_node_t nodetyp, void *error_path);

Version 19.10-12 Page 41

Page 42: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Example:

...

/* if error: set the res, errorstr, and errorval parms */ if (res != NO_ERR) { agt_record_error(scb,

&msg->mhdr, NCX_LAYER_CONTENT, res, NULL, NCX_NT_STRING, errorstr, NCX_NT_VAL, errorval);

}

...

agt_record_error API function generates an rpc_err_rec_t and save it in the message. Alternatively, agt_record_error_errinfo, agt_record_warning, agt_record_attr_error, etc API functions could be used to record an error.

The API functions, used in this code break are the most utilized and prominent functions. These functions are getting used in the SIL code often.

To summarize, anytime an <edit-config> operation loads specific “interface” configuration to the running datastore, the callback will be invoked and run.

Assuming the “interfaces” container preexist in the datastore. To invoke the callback the following RPC can be sent:

<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <edit-config> <target> <candidate/> </target> <config> <interfaces xmlns="http://yumaworks.com/ns/ietf-interfaces-example"> <interface>

<name>supported</name>

</interface> </interfaces>

</config> </edit-config> </rpc>

When the incoming configuration has been safely loaded onto the candidate datastore and validated, it is ready to impact the running system. If the device supports the :candidate capability, use the <commit> operation to apply candidate configuration to running datastore. Otherwise, if the device supports :writable-running capability, in the above <edit-config> operation example, change target to running.

Version 19.10-12 Page 42

Page 43: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The server may reply with the following:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <ok/> </rpc-reply>

If we change the “interface” name in the previous <edit-config> to “not-supported”, the server will reply with:

<errors xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx" xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf"> <error> <error-type>rpc</error-type> <error-tag>operation-not-supported</error-tag> <error-app-tag>no-support</error-app-tag> <error-message xml:lang="en">operation not supported</error-message> <error-info> <error-number>273</error-number> </error-info> </error> </errors>

Now that the incoming configuration has been integrated into the running configuration and all the callbacks run their validation and processed all the nodes, the application needs to gain trust that the change has affected the device in the way intended without affecting it negatively.

To gain this confidence, the application can run tests of the operational state of the device. The nature of the test is dependent on the nature of the change and is outside the scope of this document. Depending on the changes that have been applied on running datastore, these tests may include reachability from the system running the application (using ping), changes in reachability to the rest of the network (by comparing the device's routing table), or, for instance, inspection of the particular change (looking for operational evidence of the BGP peer that was just added).

Version 19.10-12 Page 43

Page 44: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1.2 EDIT1 Callback Initialization and Cleanup

The EDIT1 callback function is hooked into the server with the agt_cb_register_callback function, described below. The SIL code generated by yangdump-pro uses this function to register a single callback function for all callback phases.

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the EDIT1 callbacks registration may look as follows.

Register Callback Function

extern status_t agt_cb_register_callback (const xmlChar *modname,

const xmlChar *defpath, const xmlChar *version, agt_cb_fn_t cbfn);

agt_cb_register_callback

Parameter Description

modname Module name string that defines this object node.

defpath Absolute path expression string indicating which node the callback function is for.

version If non-NULL, indicates the exact module version expected.

cbfn The callback function address. This function will be used for all callback phases.

Version 19.10-12 Page 44

Page 45: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Register Callback Example

#define EXAMPLE_MODNAME (const xmlChar *)"ietf-interfaces-example"#define EXAMPLE_VERSION (const xmlChar *)"2017-01-01"#define EXAMPLE_DEFPATH (const xmlChar *)"/if:interfaces/if:interface"

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

res = agt_cb_register_callback(EXAMPLE_MODNAME,

EXAMPLE_DEFPATH, EXAMPLE_VERSION, edit_callback_example);

...}

Callback Cleanup

If you register a callback for a specific object, your SIL code must unregister it during the cleanup phase, that is being called any time the server is shutting down. Also, it is getting called during restart and reload procedure.

The following example code illustrates how the EDIT1 callback can be cleaned up. The callbacks cleanup is done during module Cleanup Phase.

extern void agt_cb_unregister_callbacks (const xmlChar *modname,

const xmlChar *defpath);

agt_cb_unregister_callbacks

Parameter Description

modname Module name string that defines this object node.

defpath Absolute path expression string indicating which node the callback function is for.

Version 19.10-12 Page 45

Page 46: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Callback Cleanup Example

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... agt_cb_unregister_callbacks (EXAMPLE_MODNAME, EXAMPLE_DEFPATH);

...}

NOTE:

The unregister function can be called just once for a specific object. It will unregister EDIT1, EDIT2, and even GET2 callbacks for the object. However, if it is called multiple times for the same object, it will return with NO errors.

All other callbacks that the object may hold should be unregistered separately.

Version 19.10-12 Page 46

Page 47: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1.3 EDIT1 Callback Function Example

In this example, the callback code forces Rollback Phase if a new value of an “interface” list is not acceptable. Otherwise an agent can process to the next step and run device instrumentation as required.

A new list validation, in this example, is done during “commit” phase. A new value is already written to the datastore (valueis getting written during apply phase) which means the server will have to reverse the edit. The server will automatically delete just created new list element from the datastore and restore the state to the initial state, to the state before the edit.

/********************************************************************* FUNCTION edit1_callback_example* * Callback function for server object handler * Used to provide a callback sub-mode for * a specific named object** Path: /interfaces/interface* Add object instrumentation in COMMIT phase.* ********************************************************************/static status_t edit1_callback_example (ses_cb_t *scb,

rpc_msg_t *msg, agt_cbtyp_t cbtyp, op_editop_t editop, val_value_t *newval, val_value_t *curval)

{ status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval; const xmlChar *errorstr = (errorval) ? NCX_NT_VAL : NCX_NT_NONE;

/* try to find a key value of the /interfaces list to validate */ val_value_t *child_val = NULL; if (newval) { child_val = val_find_child(newval, EXAMPLE_MODNAME, (const xmlChar *)"name");

if (child_val && typ_is_string(VAL_BTYPE(child_val))) { log_info("\ncallback for %s editop, test child name=%s", op_editop_name(editop), VAL_STR(child_val)); } }

switch (cbtyp) { case AGT_CB_VALIDATE: /* description stmt validation here */ break; case AGT_CB_APPLY: /* database manipulation done here */ break; case AGT_CB_COMMIT: /* device instrumentation done here */ switch (editop) { case OP_EDITOP_LOAD: interface_enabled = TRUE;

Version 19.10-12 Page 47

Page 48: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

break; case OP_EDITOP_MERGE: break; case OP_EDITOP_REPLACE: break; case OP_EDITOP_CREATE: interface_enabled = TRUE;

/* Force Rollback if the key value is not acceptable */ if (newval && child_val && typ_is_string(VAL_BTYPE(child_val)) && !xml_strcmp(VAL_STR(child_val), (const xmlChar *)"not-supported")) {

log_info("\nKey value is not supported for %s editop, name=%s", op_editop_name(editop), VAL_STR(child_val));

/* Validation failed if a key value is not supported */ errorval = child_val; res = ERR_NCX_OPERATION_NOT_SUPPORTED; } else { /* Run device instrumentation here */ } break; case OP_EDITOP_DELETE: interface_enabled = FALSE; break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

break; case AGT_CB_ROLLBACK: /* undo device instrumentation here */ break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

/* if error: set the res, errorstr, and errorval parms */ if (res != NO_ERR) { agt_record_error(scb,

&msg->mhdr, NCX_LAYER_CONTENT, res, NULL, NCX_NT_STRING, errorstr, NCX_NT_VAL, errorval);

} return res;

} /* edit_callback_example */

Version 19.10-12 Page 48

Page 49: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Now, let us go through the most eminent parts of the above example. In the following part of the above code example we are trying to find “name” key node of the edited “interface” list.

...

val_value_t *child_val = NULL; if (newval) { child_val = val_find_child(newval, EXAMPLE_MODNAME, (const xmlChar *)"name");

if (child_val && typ_is_string(VAL_BTYPE(child_val))) { log_info("\ncallback for %s editop, test child name=%s", op_editop_name(editop), VAL_STR(child_val)); } }

...

val_find_child API function finds the specified child node. Alternatively, val_find_child_fast, val_find_child_obj, val_find_child_que, etc API functions could be used to retrieve the desired value.

typ_is_string API function checks if the base type is a simple string to use this string later for logging. Alternatively, typ_is_enum, typ_is_number, etc API functions could be used to check the desired type.

VAL_BTYPE() and VAL_STR() macros are used to access val_value_t structure and get the information about its base type and get string value. If the type of the value would be an integer, for example, VAL_INT32, VAL_UINT16, etc. macros could be used to retrieve the actual set value of it.

In the following part of the above code example we are trying to validate previously retrieved key value. If the provided in the <edit-config> key value is not acceptable as specified below, then the status_t res pointer will be set to ERR_NCX_OPERATION_NOT_SUPPORTED enumeration value, that would signal to record an error and rollback the <edit-config> operation.

...

/* Force Rollback if the key value is not acceptable */ if (newval && child_val && typ_is_string(VAL_BTYPE(child_val)) && !xml_strcmp(VAL_STR(child_val), (const xmlChar *)"not-supported")) {

log_info("\nKey value is not supported for %s editop, name=%s", op_editop_name(editop), VAL_STR(child_val));

/* Validation failed if a key value is “not-supported” */ errorval = child_val; res = ERR_NCX_OPERATION_NOT_SUPPORTED; } else { /* Run device instrumentation here */ }

...

Version 19.10-12 Page 49

Page 50: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1.4 EDIT2 Callback Initialization and Cleanup

The EDIT2 callback function is hooked into the server with the agt_cb_register_edit2_callback function, described below. The SIL code generated by yangdump-pro uses this function to register a single callback function for all callback phases.

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with EDIT2 callback registration may look as follows:

Register EDIT2 Callback

extern status_t agt_cb_register_edit2_callback (const xmlChar *modname, const xmlChar *defpath, const xmlChar *version, agt_cb_fn_t cbfn);

agt_cb_register_edit2_callback

Parameter Description

modname Module name string that defines this object node.

defpath Absolute path expression string indicating which node the callback function is for.

version If non-NULL, indicates the exact module version expected.

cbfn The callback function address. This function will be used for all callback phases.

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

res = agt_cb_register_edit2_callback(EXAMPLE_MODNAME,

EXAMPLE_DEFPATH,

Version 19.10-12 Page 50

Page 51: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

EXAMPLE_VERSION, edit2_callback_example);

...}

EDIT2 Callback Cleanup

extern void agt_cb_unregister_callbacks (const xmlChar *modname,

const xmlChar *defpath);

If you register a callback for a specific object, your SIL code should unregister it during the cleanup phase, that is being called any time the server is shutting down. Also, it is getting called during a restart and reload procedure.

NOTE:

The unregister function can be called just once for a specific object. It will unregister EDIT1, EDIT2, and even GET2 callbacks for the object. However, if it is called multiple times for the same object, it will return with NO errors.

All other callbacks that the object may hold should be unregistered separately.

The following example code illustrates how the EDIT2 callback can be cleaned up. The callbacks cleanup is getting done during module Cleanup Phase.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... agt_cb_unregister_callbacks (EXAMPLE_MODNAME, EXAMPLE_DEFPATH);

...}

Version 19.10-12 Page 51

Page 52: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1.5 EDIT2 Callback Function Example

The following sections illustrates how to utilize the EDIT2 callbacks in examples.

The EDIT2 callback template is the same as the EDIT1 callback. The difference is that there is a queue of child edit records that may need to be accessed to reliably process the edit requests.

In the following example, EDIT2 callback code gets each child_undo record in order to retrieve the real edited nodes and the edited operation and merely form the data and prints it to the log. Instead of printing the data an agent could process to the next step and run device instrumentation as required.

The following example code illustrates how the EDIT2 callback may look like.

/******************************************************************** * FUNCTION edit2_callback_example * * Callback function for server object handler * Used to provide a callback sub-mode for * a specific named object * * Path: /interfaces/interface * Add object instrumentation in COMMIT phase. * ********************************************************************/ edit2_callback_example (ses_cb_t *scb, rpc_msg_t *msg, agt_cbtyp_t cbtyp, op_editop_t editop, val_value_t *newval, val_value_t *curval) { status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

if (LOGDEBUG) { log_debug("\nEnter edit2_callback_example callback for %s phase", agt_cbtype_name(cbtyp)); }

switch (cbtyp) { case AGT_CB_VALIDATE: /* description-stmt validation here */ break; case AGT_CB_APPLY: /* database manipulation done here */ break; case AGT_CB_COMMIT: /* device instrumentation done here */ switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: /* the edit is not really on this node; need to get * each child_undo record to get the real edited nodes * and the edited operations */ agt_cfg_transaction_t *txcb = RPC_MSG_TXCB(msg);

Version 19.10-12 Page 52

Page 53: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

agt_cfg_undo_rec_t *child_edit = agt_cfg_first_child_edit(txcb, newval, curval);

while (child_edit) { op_editop_t child_editop = OP_EDITOP_NONE; val_value_t *child_newval = NULL; val_value_t *child_curval = NULL; xmlChar *newval_str = NULL; xmlChar *curval_str = NULL;

agt_cfg_child_edit_fields(child_edit, &child_editop, &child_newval, &child_curval);

if (child_newval) { newval_str = val_make_sprintf_string(child_newval); if (newval_str == NULL) { return ERR_INTERNAL_MEM; } } if (child_curval) { curval_str = val_make_sprintf_string(child_curval); if (curval_str == NULL) { m__free(newval_str); return ERR_INTERNAL_MEM; } }

log_info("\n %s: editop=%s newval=%s curval=%s", child_newval ? VAL_NAME(child_newval) : NCX_EL_NULL, child_editop ? op_editop_name(child_editop) : NCX_EL_NONE, child_newval ? newval_str : NCX_EL_NULL, child_curval ? curval_str : NCX_EL_NULL);

/* Force Rollback if the child value is not acceptable */ if (child_newval && !xml_strcmp(VAL_NAME(child_newval), (const xmlChar *)"untagged-ports") && !xml_strcmp(VAL_STR(child_newval), (const xmlChar *)"not-supported")) {

res = ERR_NCX_OPERATION_NOT_SUPPORTED; m__free(newval_str); m__free(curval_str); break; }

/**** process child edits here ****/

m__free(newval_str); m__free(curval_str);

child_edit = agt_cfg_next_child_edit(child_edit); }

break; case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: /* the edit is on this list node and the child editop * can be treated the same as the parent (even if different)

Version 19.10-12 Page 53

Page 54: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* the val_value_t child nodes can be accessed and there * are no child_undo records to use */ val_value_t *child_newval = NULL; child_newval = val_find_child(newval, EXAMPLE_MODNAME, (const xmlChar *)"untagged-ports");

val_value_t *leaflist_val = child_newval; while (leaflist_val) {

/**** process child leaf-list edits here ****/

leaflist_val = val_next_child_same(leaflist_val); }

/**** process other child edits here if needed ****/

break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); } break; case AGT_CB_ROLLBACK: /* undo device instrumentation here */ break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* edit2_callback_example */

NOTE:

Do not use SET_ERROR() macro to return normal errors. This macro will cause “assert()” to be invoked, halting programexecution. The macro defined in netconf/src/ncx/status.h and it is for flagging internal errors only. This macro must not beused for normal errors.

Now, let us go through the most eminent parts of the above example.

Version 19.10-12 Page 54

Page 55: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

In the following part of the above code example we are trying to write a log with the information that the callback is gettingcalled. This is completely optional and is not required code, the main purpose of this code is to provide fast way to debug problems.

...

if (LOGDEBUG) { log_debug("\nEnter edit2_callback_example callback for %s phase", agt_cbtype_name(cbtyp)); }

...

The agt _cbtype_name API function merely gets the string for the server callback phase to print it out.

NOTE:

If the operation is “merge”, the edit is not really on this node; need to get each child_undo record to get the real edited nodes and the edited operations.

Otherwise, the edit is on the list node and the child edit operation can be treated the same as the parent (even if different) the val_value_t child nodes can be accessed and there are no child_undo records to use.

The following part of the above example code is the most important in the EDIT2 callbacks. If the operation is set to “merge”, it means that some of the children of the current node have been modified. The edit is not really on the current node, and we need to get each child undo record to get the real edited nodes and the edited operations.

In order to do so, we need to loop through the child undo records and retrieve the actual operation and the actual child node that has been modified.

NOTE:

If the parent operation is “merge” and the actual edit is on the node with default value. The edited node has a “default” YANG statement, then the actual child edit operation will always be “merge”. The difference will be in the newval, curval values.

The default children nodes should be handled carefully. If the edited node has “default” YANG statement, then the actual child edit operation will always be “merge” and curval, newval will always be set. The difference will be in newval, curval values. The following table illustrates what values will be set for those nodes:

Action Newval value Curval value

create default node new non-default value default value

modify default new non-default or set old non-default value

Version 19.10-12 Page 55

Page 56: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Action Newval value Curval value

node back to default value

delete default node default value old non-default value

The following code demonstrates how to loop through the child undo records and retrieve the actual operation and the actual child nodes. After the retrieval, the code merely logs the edited nodes into the log file and, in addition, it validates a child value to make sure that the value is appropriate for the node.

...

case OP_EDITOP_MERGE: agt_cfg_transaction_t *txcb = RPC_MSG_TXCB(msg); agt_cfg_undo_rec_t *child_edit = agt_cfg_first_child_edit(txcb, newval, curval);

while (child_edit) { op_editop_t child_editop = OP_EDITOP_NONE; val_value_t *child_newval = NULL; val_value_t *child_curval = NULL; xmlChar *newval_str = NULL; xmlChar *curval_str = NULL;

agt_cfg_child_edit_fields(child_edit, &child_editop, &child_newval, &child_curval); if (child_newval) { newval_str = val_make_sprintf_string(child_newval); if (newval_str == NULL) { return ERR_INTERNAL_MEM; } } if (child_curval) { curval_str = val_make_sprintf_string(child_curval); if (curval_str == NULL) { m__free(newval_str); return ERR_INTERNAL_MEM; } }

log_info("\n %s: editop=%s newval=%s curval=%s", child_newval ? VAL_NAME(child_newval) : NCX_EL_NULL, child_editop ? op_editop_name(child_editop) : NCX_EL_NONE, child_newval ? newval_str : NCX_EL_NULL, child_curval ? curval_str : NCX_EL_NULL);

/* Force Rollback if the child value is not acceptable */ if (child_newval && !xml_strcmp(VAL_NAME(child_newval), (const xmlChar *)"untagged-ports") && !xml_strcmp(VAL_STR(child_newval), (const xmlChar *)"not-supported")) {

Version 19.10-12 Page 56

Page 57: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

res = ERR_NCX_OPERATION_NOT_SUPPORTED; m__free(newval_str); m__free(curval_str); break; }

/**** process child edits here ****/

m__free(newval_str); m__free(curval_str);

child_edit = agt_cfg_next_child_edit(child_edit); }

break;

...

The following code illustrates how to loop through the children undo records in order to retrieve the actual operation and the actual edited children:

...

agt_cfg_undo_rec_t *child_edit = agt_cfg_first_child_edit(txcb, newval, curval);

while (child_edit) { op_editop_t child_editop = OP_EDITOP_NONE; val_value_t *child_newval = NULL; val_value_t *child_curval = NULL;

agt_cfg_child_edit_fields(child_edit, &child_editop, &child_newval, &child_curval);

/**** process child edits here ****/

child_edit = agt_cfg_next_child_edit(child_edit); }

...

The agt_cfg_first_child_edit, agt_cfg_next_child_edit, agt_cfg_child_edit_fields API functions get the first, next child node edit record, and this edit record fields respectively. There is no any alternative functions that could be used to retrieve the desired child undo records. This loop merely loops trough all the edited children and is trying to retrieve their fields, such as child new value, current value, and an actual operation that have been applied to the child node.

After we retrieve any children edits, we can process them as required. The following example code demonstrates how to logthe edited nodes into the log file:

Version 19.10-12 Page 57

Page 58: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

...

if (child_newval) { newval_str = val_make_sprintf_string(child_newval); if (newval_str == NULL) { return ERR_INTERNAL_MEM; } } if (child_curval) { curval_str = val_make_sprintf_string(child_curval); if (curval_str == NULL) { m__free(newval_str); return ERR_INTERNAL_MEM; } }

log_info("\n %s: editop=%s newval=%s curval=%s", child_newval ? VAL_NAME(child_newval) : NCX_EL_NULL, child_editop ? op_editop_name(child_editop) : NCX_EL_NONE, child_newval ? newval_str : NCX_EL_NULL, child_curval ? curval_str : NCX_EL_NULL);

m__free(newval_str); m__free(curval_str);

...

The val_make_sprintf_string API function malloc a buffer and fill it with a zero-terminated string representation of the value node. Make sure that the malloced buffer is freed after you use it. Use m__free to free the malloced buffer.

In the following part of the above code example we are trying to validate previously retrieved child “untagged-ports” node value. If the provided in the <edit-config> value is not acceptable as specified below, then the status_t res pointer will be set to ERR_NCX_OPERATION_NOT_SUPPORTED enumeration value, that would signal to record an error and rollback the <edit-config> operation.

...

if (child_newval && !xml_strcmp(VAL_NAME(child_newval), (const xmlChar *)"untagged-ports") && !xml_strcmp(VAL_STR(child_newval), (const xmlChar *)"not-supported")) {

res = ERR_NCX_OPERATION_NOT_SUPPORTED; m__free(newval_str); m__free(curval_str); break; }

...

If the operation is not “merge”, it mean that the current <edit-config> is on the “interface” list and not on its children. The edit is on the list node and the child edit operation can be treated the same as the parent (even if different) the val_value_t child nodes can be accessed the same way as for EDIT1 callback functions and there are no child_undo records to use. The

Version 19.10-12 Page 58

Page 59: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

following code break illustrates how to access “untagged-ports” leaf-list children that are getting created along with their “interface” parent:

...

case OP_EDITOP_CREATE: val_value_t *child_newval = NULL; child_newval = val_find_child(newval, EXAMPLE_MODNAME, (const xmlChar *)"untagged-ports");

val_value_t *leaflist_val = child_newval; while (leaflist_val) {

/**** process child leaf-list edits here ****/

leaflist_val = val_next_child_same(leaflist_val); }

/**** process other child edits here if needed ****/

break;

...

The val_next_child_same API function gets the next instance of the corresponding child node. This API function is useful for leaf-list and list in order to get the next sibling in the list or leaf-list.

In the following code we are trying to record an error if some of the previous steps fail. This error will be sent to the client side signaling that the <edit-config> operation failed to complete.

if (res != NO_ERR) { agt_record_error(scb,

&msg->mhdr, NCX_LAYER_CONTENT, res, NULL, NCX_NT_STRING, errorstr, NCX_NT_VAL, errorval);

}

The agt_record_error API function generates an rpc_err_rec_t and save it in the message. Alternatively, agt_record_error_errinfo, agt_record_warning, agt_record_attr_error, etc API functions could be used to record an error.

The API functions, used in this code break are the most utilized and prominent functions. These functions are getting used in the SIL code often.

To summarize, anytime an <edit-config> operation creates a new or modifies an existent “interface” list node or its childrenthe callback will be invoked and run. As described earlier, if the <edit-config> operation creates a new list entry, the

Version 19.10-12 Page 59

Page 60: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

operation will be “create” and any children that are getting created along with its parent should be treated as regular nodes and should be accessed the same way as for EDIT1 callback. However, if the operation is “merge”, the actual operation andedit is on children nodes, so the according code and actions should be applied.

Assuming the “interfaces” container and “interface” list preexist in the datastore. However, assume there is not any other children on this list other than the key child. To invoke the callback with “merge” operation the following RPC can be sent:

<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <edit-config> <target> <candidate/> </target> <config> <interfaces xmlns="http://yumaworks.com/ns/ietf-interfaces-example"> <interface>

<name>supported</name>

<untagged-ports>port1</untagged-ports> <untagged-ports>port2</untagged-ports> <untagged-ports>port3</untagged-ports> <untagged-ports>port4</untagged-ports>

</interface> </interfaces>

</config> </edit-config> </rpc>

As a result, the server will invoke the callback with “merge” operation; however, the actual operation is “create” and the actual edit is on “untagged-ports” leaf-list. So, you will have to loop trough the children and retrieve the actual edits.

When the incoming configuration has been safely loaded onto the candidate datastore and validated, it is ready to impact the running system. If the device supports the :candidate capability, use the <commit> operation to apply candidate configuration to running datastore. Otherwise, if the device supports :writable-running capability, in the above <edit-config> operation example, change target to running.

This RPC and the callback function that it triggers will pass the validation and should not trigger any Rollback, so the server may reply with the following:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <ok/> </rpc-reply>

If we add another leaf-list entry to the <edit-config> RPC with the “not-supported” value, then the server should reply with the following error (based on the SIL callback validation that we created previously) and trigger Rollback phase where it should reverse any previously applied edits and restore the state to the state that was before the edit:

Version 19.10-12 Page 60

Page 61: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

<errors xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx" xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf"> <error> <error-type>rpc</error-type> <error-tag>operation-not-supported</error-tag> <error-app-tag>no-support</error-app-tag> <error-message xml:lang="en">operation not supported</error-message> <error-info> <error-number>273</error-number> </error-info> </error> </errors>

Now that the incoming configuration has been integrated into the running configuration and all the callbacks run their validation and processed all the nodes, the application needs to gain trust that the change has affected the device in the way intended without affecting it negatively.

To gain this confidence, the application can run tests of the operational state of the device. The nature of the test is dependent on the nature of the change and is outside the scope of this document. Depending on the changes that have been applied on running datastore, these tests may include reachability from the system running the application (using ping), changes in reachability to the rest of the network (by comparing the device's routing table), or, for instance, inspection of the particular change (looking for operational evidence of the BGP peer that was just added).

Version 19.10-12 Page 61

Page 62: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.1.6 EDIT2 Utility Functions

EDIT 2 mode provides extended edit functionality and thus more ways to manage specific edit.

There are EDIT 2 mode specific high-level Transaction access and management utilities in netconf/src/agt/agt_cfg.h. These functions access the lower-level functions to provide simpler functions for common transaction management tasks.

The following table highlights available functions:

API Description

agt_cfg_first_child_edit() Get the first child node edit record for a given transaction.

agt_cfg_next_child_edit() Get the child edit fields from the undo record.

agt_cfg_child_edit_fields() Get the child edit fields from the specified undo record.

agt_cfg_first_child_undo() Get the first child undo record for EDIT2 mode

agt_cfg_next_child_undo() Get the next child undo record

Version 19.10-12 Page 62

Page 63: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.2 GET1 Callback

This section describes how to manage non-configurable or just operational data, what type of callbacks are available for non-configurable nodes and how to utilize these type of callbacks.

Operational data nodes are supported within SIL code in three ways:

1. value node based virtual data (GET1 callback)

2. value node based static data (GET1 callback)

3. object template based GET2 callback

The following function template definition is used for GET1 callback functions:

typedef status_t (*getcb_fn_t) (ses_cb_t *scb,

getcb_mode_t cbmode, const val_value_t *virval, val_value_t *dstval);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per object

• File: getcb.h

• Template: getcb_fn_t

◦ Inputs:

▪ scb == session that issued the get (may be NULL) , can be used for access control purposes

▪ cbmode == reason for the callback

▪ virval == place-holder node in the data model for this virtual value node

▪ dstval == pointer to value output struct

◦ Outputs: fill may be adjusted depending on callback reason. Dstval should be filled in, depending on the callback reason.

◦ Returns: status_t:Status of the callback function execution.

• Register: none

• Unregister: none

Where, SCB pointer represents a session control block structure that is defined in the netconf/src/ncx/ses.h. This control block is primarily used for error reporting. However, it also provides access to the session specific information, such as current message input/output encoding, current session ID information, current protocol information, user name information, peer address information, etc. Note, all the fields in this structure should NOT be changed and accessed directly. This control block ideally should be used only for getting more information about the current session, not for alteration of any of its fields.

Version 19.10-12 Page 63

Page 64: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

CBMODE pointer represents an enumeration structure of the different server GET callback retrieval types that is defined inthe netconf/src/ncx/getcb.h. This control block specifies what retrieval type has this GET callback. GET1 callback shouldhave GETCB_GET_VALUE type, if the type is different, the error should be reported, as specified in the examples later inthis section.

VIRVAL pointer represents a data node as a place-holder node in the data model for this virtual value node. It is defined in the netconf/src/ncx/getcb.h. This control block specifies what operation is in the process, merge, replace, delete, or other, as described in the example section later.

DSTVAL pointer represent data nodes that is being filled in. The example section later demonstrates how it can be utilized.

5.2.1 GET1 Callback Examples. Virtual data

A common SIL callback function to use is a virtual node 'get' function. A virtual node can be either a configuration or non-configuration node, but is more likely to be a non-configuration node, such as a counter or hardware status object. Use virtual operational data when the data is stored in the running system somewhere and the values need to be retrieved from the system in order to fill the YANG data nodes in the <rpc-reply>.

This type of callbacks also called - GET1 callbacks and they can be used during SIL initialization phase or during the <edit-config> operation.

To exemplify, when the incoming configuration for /interfaces/interface has been safely loaded onto the device and validated and you want read-only leafs to be populated at the same time, then the callback function may be implemented as follows. In this example we use already existent EDIT1 callback where we extend it with a GET1 callback function:

The function that is responsible for the GET1 callback may look as follows:

/******************************************************************** * FUNCTION create_readonly_leaf* * Make read-only child nodes * Path: /interfaces/interface/observed-speed* * INPUTS: * parentval == the parent struct to use for new child nodes * * RETURNS: * error status ********************************************************************/ static status_t create_readonly_leaf (val_value_t *parentval) { status_t res = NO_ERR;

/* add /interfaces/interface/observed-speed */ val_value_t *childval =

agt_make_virtual_leaf( VAL_OBJ(parentval), (const xmlChar *)"observed-speed", observed_speed_get, &res);

if (childval != NULL) { res = val_child_add(childval, parentval); if (res != NO_ERR) { val_free_value(childval); }

Version 19.10-12 Page 64

Page 65: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

return res;

} /* create_readonly_leaf */

The following example shows a simple get callback function for the same data model, which returns the “observed-speed” element when it is requested.

/******************************************************************** * FUNCTION observed_speed_get** Callback function for agent node get handler* * Fill in 'dstval' contents * ********************************************************************/ static status_t observed_speed_get ( ses_cb_t *scb,

getcb_mode_t cbmode, const val_value_t *virval, val_value_t *dstval)

{ status_t res = NO_ERR;

/* remove the next line if scb is used */ (void)scb;

/* remove the next line if virval is used */ (void)virval;

if (cbmode != GETCB_GET_VALUE) { return ERR_NCX_OPERATION_NOT_SUPPORTED; }

/* set the speed var here */ const xmlChar *speed = (const xmlChar *)"1000"; res =

val_set_simval_obj( dstval, dstval->obj, speed);

return res;

} /* observed_speed_get */

In these examples, the following commonly used API functions were implemented:

• agt_make_virtual_leaf: Make a val_value_t structure for a specified virtual leaf or leaf-list. Alternatively, agt_add_top_virtual API function could be used if there is need to make a val_value_t structure for a specified virtual top-level data node. Refer to the section named “SIL Utility Functions” in this guide for more details.

• val_set_simval_obj: Set an initialized val_value_t as a simple type. Refer to the section named “Access Functions” in this guide for more available API and details.

The above list illustrates only the most utilized and prominent functions used in the example. These functions are getting used in the SIL code very often. To find more information on the not listed API functions refer to the corresponding .h file.

Version 19.10-12 Page 65

Page 66: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

To summarize, anytime an <edit-config> operation loads specific “interface” list node configuration to the specific target configuration, the virtual “observed-speed” node will be generated.

To ensure that the state data was successfully generated an application may retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <interfaces xmlns="http://yumaworks.com/ns/interfaces"> </interface> <name>supported</name>

</interface> </interfaces> </filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interfaces xmlns="http://yumaworks.com/ns/interfaces"> </interface> <name>supported</name>

<observed-speed>1000</observed-speed>

</interface> </interfaces> </rpc-reply>

Version 19.10-12 Page 66

Page 67: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.2.2 GET1 Callback Examples for Static Data

Let us go through simple examples that will illustrate how to utilize the GET1 callbacks based on static data and populate this static data during SIL initialization phase, so it will be available right after the module and its SIL are loaded into the server. Consider this simplified, but functional, example.

... container interfaces { list interface { key "name";

leaf name { type string; } leaf speed { type enumeration { enum 10m; enum 100m; enum auto; } } leaf observed-speed { config false; type uint32; } }

leaf count { config false; type unit32; }

}

...

leaf version { config false; type string; }

In this example we have two operational data nodes, an “observed-speed” and a “version” leaf. We just illustrated how to register the GET1 callback for the “observed-speed” leaf. Now, let us register the GET1 callback for the “version” static data leaf.

The concept is the same as in the previous example; however, the GET1 callback is getting registered and initialized duringthe SIL initialization phase.

During the Initialization Phase 1, the server will load the module:

/********************************************************************

Version 19.10-12 Page 67

Page 68: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* FUNCTION interfaces_init* * initialize the server instrumentation library* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

ncx_module_t *interface_mod = NULL;

/* load the module */ status_t res = ncxmod_load_module(EXAMPLE_MODNAME,

NULL, agt_get_savedevQ(), &interface_mod);

if (res != NO_ERR) { return res; }

...}

After the startup configuration is loaded into the running configuration database, all the stage 2 initialization routines are called. These are needed for modules which add read-only “static” data nodes to the tree containing the running configuration. SIL modules may use their 'init2' function to create factory default configuration nodes (which can be saved for the next reboot).

The Initialization Phase 2 function that creates factory default “static” configuration nodes with help of the GET1 callbacksmay look as follows:

/******************************************************************** * FUNCTION interfaces_init* * Initialize the server instrumentation library.* Called after running config is loaded** Initialization Phase 2* *********************************************************************/ static status_t interfaces_init 2 (void) { status_t res= NO_ERR;

/* get the running configuration datastore */ cfg_template_t *runningcfg = cfg_get_config_id(NCX_CFGID_RUNNING); if (!runningcfg || !runningcfg->root) { return ERR_INTERNAL_VAL; }

/* get the top object node */ obj_template_t *topobj = obj_find_template_top(interface_mod,

EXAMPLE_MODNAME,

Version 19.10-12 Page 68

Page 69: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

(const xmlChar *)"version"); if (!topobj) { return ERR_NCX_DEF_NOT_FOUND; }

/* add /version virtual node */ val_value_t *version = val_new_value(); if (!version) { return ERR_INTERNAL_MEM; } val_init_virtual(version, get_version, topobj);

/* handing off the malloced memory here */ res = val_child_add(version, runningcfg->root); if (res != NO_ERR) { val_free_value(version). }

return res;

} /* interfaces_init */

The obj_find_template_top API returns obj_template_t structure or NULL if some error; however, this function should be used only for the top level objects. Similarly, the following extended function can be used.

...

/* Get the server profile struct */ agt_profile_t *profile = agt_get_profile();

/* get the top object node */ obj_template_t *topobj =

ncx_match_any_object_ex(EXAMPLE_MODNAME, (const xmlChar *)"interfaces", TRUE, profile->agt_match_names, profile->agt_alt_names, &res); if (!topobj) {

return ERR_NCX_DEF_NOT_FOUND; }

...

Alternatively, if you know the object template that defines the object template for the parent node and would like to find specific child node object of that parent, the following API can be used:

...

obj_template_t *leafobj = obj_find_child(topobj,

EXAMPLE_MODNAM, (const xmlChar *)"count");

Version 19.10-12 Page 69

Page 70: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

if (!leafobj) { return ERR_NCX_DEF_NOT_FOUND;

}

...

The following example shows a simple GET1 callback function for the same data model, which creates factory default “static” configuration for the “observed-speed” node.

/******************************************************************** * FUNCTION get_version** Callback function for agent node get handler* * Fill in 'dstval' contents * ********************************************************************/ static status_t get_version ( ses_cb_t *scb,

getcb_mode_t cbmode, const val_value_t *virval, val_value_t *dstval)

{ status_t res = NO_ERR;

/* remove the next line if scb is used */ (void)scb;

/* remove the next line if virval is used */ (void)virval;

if (cbmode != GETCB_GET_VALUE) { return ERR_NCX_OPERATION_NOT_SUPPORTED; }

/* set the speed var here */ const xmlChar *version = (const xmlChar *)"Version1.1"; res =

val_set_simval_obj(dstval, dstval->obj, version);

return res;

} /* get_version */

Now, the static “version” node is generated during the SIL initialization phase and will available right after the server boots.

To ensure that the static data was successfully generated an application can retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?>

Version 19.10-12 Page 70

Page 71: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

<rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get/> </rpc>

The server should reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interfaces xmlns="http://yumaworks.com/ns/interfaces"> </interface> <name>supported</name>

<observed-speed>1000</observed-speed>

</interface> </interfaces>

<version>Version1.1</version> </rpc-reply>

Version 19.10-12 Page 71

Page 72: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.3 GET2 Callback

The GET2 callback functions use 1 callback per object template. The server will issue “get” and “getnext” requests via this API, and the callback code will return value nodes for the data it is managing. These data nodes are not maintained in the server Data Tree. They are not cached in the server.

Configuration data is not supported at this time. These callbacks are expected to return some or all of the terminal child nodes (leaf, leaf-list, anyxml) when invoked.

NOTE:

GET2 callbacks never return child nodes that are complex nodes. Complex child nodes are expected to have their own get2callbacks registered.

Configuration data is not supported for the GET2 callbacks.

The following function template definition is used for GET2 callback functions:

typedef status_t (*getcb_fn2_t) (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per object

• Files: getcb.h, agt_cb.h

• Template: getcb_fn2_t

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming XML message header

▪ get2cb == get2 control block for this callback request

◦ Outputs: return_keyQ is full of any new keys added for this entry -- only if 'obj' is a list return_valQ is filled with malloced val_value_t nodes. If object tested is a choice the a backptr to a constant string containing the case name that is active.

◦ Returns: status_t:Status of the callback function execution. NO_ERR if executed OK and found OK. ERR_NCX_NO_INSTANCE warning if no instance found

• Register: agt_cb_register_get_callback

• Unregister: agt_cb_unregister_callbacks

Version 19.10-12 Page 72

Page 73: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Complex child nodes are expected to have their own get2 callbacks registered. The GET2 callbacks are registered with an API similar to the EDIT callback registration.

The following node types are expected to have GET2 callbacks registered:

• choice: expected to return the name of the active case and terminal nodes from the active case

• container: expected to return child terminal nodes

• list: expected to return list keys and maybe other terminal nodes

Callbacks for terminal nodes are allowed, but only if their parent is a config=true node. The server will expect configuration data nodes to be present in the target datastore. If the retrieval request includes config=false nodes, then the server will check each child node that is config=false for a GET2 callback function. If it exists, then it will be used for retrieval of that data node. If not, the current config=true node will be checked for child nodes (static or dynamic operational data).

Each GET2 callback returns a status code

• NO_ERR: data is returned

• ERR_NCX_NO_INSTANCE: the specified data instance does not exist

• Other status code: some error occurred

YANG Node Type GET2 Callback Summary

container Returns the child terminal nodes in the container

list Returns the keys and perhaps the rest of the child terminal nodes. Set “more_data” to trigger “getnext” until no more instances found

anyxml Returns the entire anyxml value tree

leaf Returns the leaf value

leaf-list Returns all values for the leaf-list

choice Returns the name of the active case and child terminal nodes in the active case

case This node type does not have a callback

Procedure

The server will send a <get-request> server request message to each subsystem that has registered a get2 callback for the specific object.

• For single-instance nodes (container, leaf, choice, anyxml) only a “get” request will be made.

• For a leaf-list node, only “get” requests will be made, but all instances of the leaf-list are returned at once (max-entries parameter equals zero).

• For a list node, a “get” request will be made if the keys are known. A “get” request that contains no keys will cause the first instance to be returned. Entries are ordered by their key values, exactly as specified in the YANG list. If

Version 19.10-12 Page 73

Page 74: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

there is no key-stmt defined, then the callback will still return the first entry, except the server will not attempt any sorting if multiple entries are returned (i.e. 1 from each subsystem). It is always up to the callback to know what is the “best” next entry, given the keys that are returned.

The callback examined the keys (if any) and fills in the return_keys. If the “keys-only” flag is set, then no other terminal nodes are returned. If there are more list entries, then the “more-data” flag is set in the get-response. The server will issue “getnext” requests as needed until the “more-data” flag is not present in the response. The “max-entries” field will be set to 1. It may be set higher in a future release to support getbulk retrieval.

Version 19.10-12 Page 74

Page 75: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.3.1 GET2 Callback Initialization and Cleanup

The following example code illustrates how the GET2 callbacks can be registered. The callbacks registration is getting done during Initialization Phase 1.

/********************************************************************* FUNCTION agt_cb_register_get_callback* * Register an object specific GET callback function* use the same fn for all callback phases * all phases will be invoked*** INPUTS:* modname == module that defines the target object for* these callback functions * defpath == Xpath with default (or no) prefixes* defining the object that will get the callbacks* version == exact module revision date expected* if condition not met then an error will* be logged (TBD: force unload of module!)* == NULL means use any version of the module* get_cbfn == address of callback function to use for GET callbacks** RETURNS:* status*********************************************************************/extern status_t agt_cb_register_get_callback (const xmlChar *modname, const xmlChar *defpath, const xmlChar *version, getcb_fn2_t get_cbfn);

Example:

/******************************************************************** * FUNCTION init_interfaces * * initialize the server instrumentation library* *********************************************************************/ static status_t init_interfaces (void) {

...

res = agt_cb_register_get_callback(EXAMPLE_MODNAME, (const xmlChar *)"/interfaces-state", EXAMPLE_VERSION, get2_container_interfaces); if (res != NO_ERR) { return res;

Version 19.10-12 Page 75

Page 76: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

}

...

} /* init_interfaces */

The following example code illustrates how the GET2 callbacks can be cleaned up. The callbacks Cleanup is getting done during Cleanup Phase.

NOTE:

The unregister function is the same as for EDIT callbacks. It is not required to unregister GET2 callbacks for an object if an unregister function has already been called for the same object but with EDIT callback. However, if it is called multiple times for the same object, it will return with no errors.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ...

agt_cb_unregister_callbacks (EXAMPLE_MODNAME, (const xmlChar *)"/interfaces-state");

...}

Version 19.10-12 Page 76

Page 77: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.3.2 GET2 Callback Function Examples

The following sections illustrates how to utilize the GET2 callback in examples. Let us go through simple examples that will illustrate how to utilize the GET2 callbacks for the specific YANG node types.

Container exampleConsider this simplified example, that represents GET2 callback for the “interface-state” container.

...

container interfaces-state { config false;

leaf in-errors { type uint32; }...

}

...

NOTE:

The GET2 callbacks for “container” elements DO NOT required to fill in any children elements. All additional leafs are optional to fill in. Any other descendant complex elements, such as lists, other containers, and choice elements must have their own callbacks functions.

The following C API code exemplifies a simple get callback function for the data model, which returns the “interfaces-state” container element with an additional leaf element when it is requested.

/********************************************************************* FUNCTION get2_container_interfaces** Path: /interfaces-state** INPUTS: * scb == session control block making the request * msg == incoming XML message header * get2cb == get2 control block for this callback request* * OUTPUTS: * return_valQ is filled with malloced val_value_t nodes* * RETURNS: * status: * NO_ERR if executed OK and found OK * ERR_NCX_NO_INSTANCE warning if no instance found*

Version 19.10-12 Page 77

Page 78: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

********************************************************************/static status_t get2_container_interfaces (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb) { (void)scb; (void)msg;

/* check the callback mode type */ getcb_mode_t cbmode = GETCB_GET2_CBMODE(get2cb); switch (cbmode) { case GETCB_GET_VALUE: break; case GETCB_GETNEXT_VALUE: return ERR_NCX_NO_INSTANCE; default: return SET_ERROR(ERR_INTERNAL_VAL); }

/* get the template for the “interfaces-state” container */ obj_template_t *obj = GETCB_GET2_OBJ(get2cb); status_t res = NO_ERR;

/* pretend leaf 'in-errors' is present */ val_value_t *retval =

agt_make_leaf2(obj, EXAMPLE_MODNAME,

(const xmlChar *)"in-errors", (const xmlChar *)"8", &res); if (retval) { getcb_add_return_val(get2cb, retval); } else { return res; }

/* choice and other complex nodes will be checked in a separate call */

return res;

} /* get2_container_interfaces */

The agt_make_leaf2 API returns malloced value structure or NULL if some error. Alternatively, if you know the object template that defines the leaf node that you want to generate, the following more generic API can be used:

...

obj_template_t *leafobj = obj_find_child(obj,

EXAMPLE_MODNAM, (const xmlChar *)"in-errors");

if (!leafobj) { /* report an error or do not try to generate the leaf, just skip it */ return ERR_NCX_DEF_NOT_FOUND;

}

/* pretend leaf 'in-errors' is present */

Version 19.10-12 Page 78

Page 79: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_value_t *retval = val_make_simval_obj(leafobj, (const xmlChar *)"8", &res); ...

In the scenario above, make sure that the leaf object template was found. If it was not found, you may report an error immediately or ignore that node and skip the node generation process. However, do not generate the leaf node, if the object template was not found.

NOTE:

In the SIL, when you fill the data in get2cb with help of val_make_simval_obj() or analogous APIs, You don’t need to freethe buffer because the server does clean up get2cb.

To ensure that the GET2 callbacks are working as expected an application may retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <interfaces-state xmlns="http://yumaworks.com/ns/ietf-interfaces-example" />

</filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interfaces-state xmlns="http://yumaworks.com/ns/ietf-interfaces-example"> <in-errors>8</in-errors>

</interfaces-state> </rpc-reply>

Now let us go through simple examples that will illustrate how to utilize the GET2 callbacks for “list” nodes.

Version 19.10-12 Page 79

Page 80: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

List exampleConsider this simplified example, that represents GET callback for the “interface” list.

...

container interfaces-state { config false;

list interface { key "ip";

leaf ip {

type inet:ip-prefix; }

leaf name { type string; mandatory true; } }

... }

...

NOTE:

The GET2 callbacks for “list” elements DO require to fill in the list key value. All additional leafs are optional to fill in. Any other descendant complex elements, such other lists, containers, or choice nodes must have their own callbacks functions.

The following C API code exemplifies a simple GET2 callback function for the data model, which returns the “interface” list element with an additional leaf elements when it is requested.

/********************************************************************* FUNCTION get2_list_interface** Path: /interfaces-state/interface** INPUTS: * scb == session control block making the request * msg == incoming XML message header * get2cb == get2 control block for this callback request* * OUTPUTS: * return_valQ is filled with malloced val_value_t nodes* return_keyQ is filled with any new keys added for this entry ** RETURNS: * status:

Version 19.10-12 Page 80

Page 81: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* NO_ERR if executed OK and found OK * ERR_NCX_NO_INSTANCE warning if no instance found*********************************************************************/static status_t get2_list_interface (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb) { (void)scb; (void)msg;

uint32 max_entries = GETCB_GET2_MAX_ENTRIES(get2cb); (void)max_entries;

boolean getnext = FALSE;

/* check the callback mode type */ getcb_mode_t cbmode = GETCB_GET2_CBMODE(get2cb); switch (cbmode) { case GETCB_GET_VALUE: break; case GETCB_GETNEXT_VALUE: getnext = TRUE; break; default: return SET_ERROR(ERR_INTERNAL_VAL); }

/* get the list and child objects */ obj_template_t *obj = GETCB_GET2_OBJ(get2cb); obj_template_t *key_obj = obj_find_child(obj, EXAMPLE_MODNAME, (const xmlChar *)"ip");

/* init leaf values for the list */ const xmlChar *name = NULL; const xmlChar *ret_name = NULL; boolean name_fixed = FALSE;

/* check the keyQ for the specific list instance requested */ val_value_t *name_key = getcb_find_key(get2cb, key_obj);

/* pretend there are 3 values */ #define IP1 (const xmlChar *)"10.10.10.1/16" #define IP2 (const xmlChar *)"10.10.10.2/16" #define IP3 (const xmlChar *)"10.10.10.3/16"

/* specific list instance requested, check if it is valid */ if (name_key && VAL_STR(name_key)) { name = VAL_STR(name_key); int32 ret = xml_strcmp(name, IP2); if (ret > 0) { return ERR_NCX_NO_INSTANCE; }

/* specific list instance requested, set the flag */ name_fixed = VAL_IS_FIXED_VALUE(name_key); }

/* set to true if there are more instances of this object to retrieve;

Version 19.10-12 Page 81

Page 82: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* false otherwise */ boolean moreflag = TRUE;

/* check validity of keys present */ if (getnext) { if (name_fixed) { return ERR_NCX_NO_INSTANCE; }

/* adjust the key to find the next entry after * the specified value */ if (!name) { ret_name = IP1; // return first entry [0] } else { /* find the correct entry to retrieve */ int32 ret = xml_strcmp(name, IP1); if (ret < 0) { ret_name = IP1; } else if (ret == 0) { ret_name = IP2; } else { /* check IP2 */ ret = xml_strcmp(name, IP2); if (ret < 0) { ret_name = IP2; } else if (ret == 0) { ret_name = IP3; moreflag = FALSE; } else { /* assume IP3 */ ret_name = IP3; moreflag = FALSE; } } } } else { if (name) { /* get a specified instance */ boolean name_ok = FALSE; if (!xml_strcmp(name, IP1)) { name_ok = TRUE; } else if (!xml_strcmp(name, IP2)) { name_ok = TRUE; } else if (!xml_strcmp(name, IP3)) { name_ok = TRUE; moreflag = FALSE; } if (name_ok) { ret_name = name; } else { return ERR_NCX_NO_INSTANCE; } } else { // else no keys == get-first ret_name = IP1; } }

GETCB_GET2_MATCH_TEST_DONE(get2cb) = FALSE;

if (ret_name == NULL) {

Version 19.10-12 Page 82

Page 83: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

return ERR_NCX_NO_INSTANCE; }

GETCB_GET2_MORE_DATA(get2cb) = moreflag;

status_t res = NO_ERR;

/* if we get here then the index is valid * * create a return_keyQ node for the name key value */ val_value_t *return_val = agt_make_leaf2(obj, EXAMPLE_MODNAME, (const xmlChar *)"ip", ret_name, &res); if (res == NO_ERR) { if (name_fixed) { VAL_SET_FIXED_VALUE(return_val); } getcb_add_return_key(get2cb, return_val); }

/* Also, pretend leaf 'name' is present * Here, might be another key name validation that will dictate what “name” * value to use based on key value. * Note, “name” leaf is a mandatory=true leaf, so it must be present. */ val_value_t *retval =

agt_make_leaf2(obj, EXAMPLE_MODNAME,

(const xmlChar *)"name", (const xmlChar *)"interface-name", &res); if (retval) { getcb_add_return_val(get2cb, retval); } else { return res; }

return NO_ERR;

} /* get2_list_interface */

Refer to the section named “GET2 Access Functions” for other available functions to access GET2 control block.

To ensure that the GET2 callbacks are working as expected an application can retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <interfaces-state xmlns="http://yumaworks.com/ns/ietf-interfaces-example">

<interface><ip>10.10.10.1/16</ip>

Version 19.10-12 Page 83

Page 84: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

</interface> </interfaces-state> </filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interfaces-state xmlns="http://yumaworks.com/ns/ietf-interfaces-example">

<interface><ip>10.10.10.1/16</ip> <ip>interface-name</ip>

</interface> </interfaces-state> </rpc-reply>

If no key value is specified in the request or the request subtree filter target is “interface-state” parent container, then the server will try to output all the interfaces and its children:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <interfaces-state xmlns="http://yumaworks.com/ns/ietf-interfaces-example" />

</filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interfaces-state xmlns="http://yumaworks.com/ns/ietf-interfaces-example">

<interface><ip>10.10.10.1/16</ip> <ip>interface-name</ip>

</interface> <interface>

<ip>10.10.10.2/16</ip> <ip>interface-name</ip>

</interface> <interface>

Version 19.10-12 Page 84

Page 85: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

<ip>10.10.10.3/16</ip> <ip>interface-name</ip>

</interface> </interfaces-state> </rpc-reply>

Now let us go through simple examples that will illustrate how to utilize the GET2 callbacks for “choice” node.

Version 19.10-12 Page 85

Page 86: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Choice exampleConsider this simplified example, that represents GET callback for the node type “choice”.

...

choice type { case interface { // active case leaf interface { type if:interface-ref; } }

case case-network { leaf next-hop-host { type inet:ip-address; } } }

...

The following C API code exemplifies a simple get callback function for the data model, which returns the name of the active case and child terminal nodes in the active case when it is requested.

/********************************************************************* FUNCTION get2_choice_type** Path: /type** INPUTS: * scb == session control block making the request * msg == incoming XML message header * get2cb == get2 control block for this callback request* * OUTPUTS: * return_valQ is filled with malloced val_value_t nodes* the a backptr to a constant string containing the case * name that is active** RETURNS: * status: * NO_ERR if executed OK and found OK * ERR_NCX_NO_INSTANCE warning if no instance found*********************************************************************/static status_t get2_choice_type (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb) { (void)scb; (void)msg; status_t res = NO_ERR;

Version 19.10-12 Page 86

Page 87: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* check the callback mode type */ getcb_mode_t cbmode = GETCB_GET2_CBMODE(get2cb); switch (cbmode) { case GETCB_GET_VALUE: break; case GETCB_GETNEXT_VALUE: return ERR_NCX_NO_INSTANCE; default: return SET_ERROR(ERR_INTERNAL_VAL); }

/* get the active case * callback based on instances in the system * It may be NULL if no active case */ const xmlChar *active_case_modname = NULL; const xmlChar *active_case = (const xmlChar *)"interface";

/* Set the active case to the specified object */ res = getcb_set_active_case(get2cb, active_case_modname, active_case);

if (active_case == NULL) { return res; }

/* get the template for the active case */ obj_template_t *choice_obj = GETCB_GET2_OBJ(get2cb); if (choice_obj == NULL) { return ERR_NCX_NOT_FOUND; }

obj_template_t *case_obj = obj_find_child(choice_obj, active_case_modname, active_case); if (case_obj == NULL) { return ERR_NCX_NOT_FOUND; }

/* return all the leaf and leaf-list instances that are child nodes * of the active case. */ val_value_t *chval = NULL;

if (!xml_strcmp(active_case, (const xmlChar *)"interface")) { /* pretend leaf 'interface' is present */ chval = agt_make_leaf2(case_obj, active_case_modname, (const xmlChar *)"interface", (const xmlChar *)"ethernet1/1/1", &res); if (chval) { getcb_add_return_val(get2cb, chval); } else { return res; } } else { res = SET_ERROR(ERR_INTERNAL_VAL); }

return res;

Version 19.10-12 Page 87

Page 88: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

} /* get2_choice_type */

NOTE:

Note that any leaf or leaf-list nodes that are in nested “choice” element within the active case are not returned . These are considered complex objects and the caller will ask for nested choice, list, and container nodes in a separate call .

Refer to the section named “GET2 Access Functions” for other available functions to access GET2 control block.

To ensure that the GET2 callback is working as expected an application can retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <interface xmlns="http://yumaworks.com/ns/interfaces" />

</filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">

<interface xmlns="http://yumaworks.com/ns/interfaces">ethernet1/1/1 </interface> </rpc-reply>

Now let us go through simple examples that will illustrate how to utilize the GET2 callbacks for the leaf and leaf-list nodes.

Version 19.10-12 Page 88

Page 89: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Leaf and leaf-list examplesConsider this simplified example, that represents GET callback for the “leaf” and “leaf-list” nodes.

...

leaf get2-leaf { config false; type int32; }

leaf-list get2-leaf-list { config false; type int32; }

...

NOTE:

Note that only leaf or leaf-list nodes that are top level nodes required a callback. Any other simple type nodes DOES NOT required callback and can be generated within their parent callback invocation.

The following C API code exemplifies a simple get callback function for the data model, which returns the leaf value when it is requested.

/* start value for leaf /get2-leaf */ static int32 leaf_val = 42;

/********************************************************************* FUNCTION get2_leaflist_type** Path: /get2-leaf** INPUTS: * scb == session control block making the request * msg == incoming XML message header * get2cb == get2 control block for this callback request* * OUTPUTS: * return_valQ is filled with malloced val_value_t nodes** RETURNS: * status: * NO_ERR if executed OK and found OK * ERR_NCX_NO_INSTANCE warning if no instance found*********************************************************************/static status_t get2_leaflist_type (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb)

Version 19.10-12 Page 89

Page 90: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

{ (void)scb; (void)msg;

/* check the callback mode type */ getcb_mode_t cbmode = GETCB_GET2_CBMODE(get2cb); switch (cbmode) { case GETCB_GET_VALUE: break; case GETCB_GETNEXT_VALUE: return ERR_NCX_NO_INSTANCE; default: return SET_ERROR(ERR_INTERNAL_VAL); }

/* get the real value from the system here. * But in this example just increment the value by 1 */ int32 retval = leaf_val++;

/* return the leaf in the static return_val struct */ obj_template_t *obj = GETCB_GET2_OBJ(get2cb); val_value_t *return_val = GETCB_GET2_RETURN_VAL(get2cb);

val_init_from_template(return_val, obj); VAL_INT32(return_val) = retval;

return NO_ERR;

} /* get2_leaflist_type */

Refer to the section named “GET2 Access Functions” for other available functions to access GET2 control block.

In the above example, the code generates the value based on the static value that is incremented after each retrieval. An agent can generate the value based on the real device statistical data or based on the system's statistical data, etc.

NOTE:

In the example, the code demonstrates how the value can be set using val.h macros, VAL_INT32. However, it is more reliable and recommended to use val.h APIs as agt_make_leaf2, or specific API for a specific YANG type, such as agt_make_int_leaf2. Or the most generic val_make_simval_obj() that creates and set a val_value_t as a simple type from an object template instead of individual fields.

To ensure that the GET2 callback is working as expected an application can retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <get2-leaf xmlns="http://yumaworks.com/ns/interfaces" />

Version 19.10-12 Page 90

Page 91: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

</filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">

<get2-leaf xmlns="http://yumaworks.com/ns/interfaces">42</get2-leaf> </rpc-reply>

Now let us go through simple examples that will illustrate how to utilize the GET2 callbacks for the leaf-list nodes.

The following C API code exemplifies a simple GET2 callback function for the same data model, which returns the leaf-listvalues when requested.

/********************************************************************* FUNCTION get2_leaflist_type** Path: /get2-leaf-list** INPUTS: * scb == session control block making the request * msg == incoming XML message header * get2cb == get2 control block for this callback request* * OUTPUTS: * return_valQ is filled with malloced val_value_t nodes** RETURNS: * status: * NO_ERR if executed OK and found OK * ERR_NCX_NO_INSTANCE warning if no instance found*********************************************************************/static status_t get2_leaflist_type (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb) { (void)scb; (void)msg;

status_t res = NO_ERR;

/* check the callback mode type */ getcb_mode_t cbmode = GETCB_GET2_CBMODE(get2cb); switch (cbmode) { case GETCB_GET_VALUE: break; case GETCB_GETNEXT_VALUE: return ERR_NCX_NO_INSTANCE;

Version 19.10-12 Page 91

Page 92: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

default: return SET_ERROR(ERR_INTERNAL_VAL); }

obj_template_t *obj = GETCB_GET2_OBJ(get2cb);

/* always return all the leaf-list instances * 3 entries [53, 67, 92] */ val_value_t *retval = val_make_simval_obj(obj, (const xmlChar *)"53", &res); if (retval) { getcb_add_return_val(get2cb, retval); }

if (res == NO_ERR) { retval = val_make_simval_obj(obj, (const xmlChar *)"67", &res); if (retval) { getcb_add_return_val(get2cb, retval); } }

if (res == NO_ERR) { retval = val_make_simval_obj(obj, (const xmlChar *)"92", &res); if (retval) { getcb_add_return_val(get2cb, retval); } }

return res;

} /* get2_leaflist_type */

In the above example, the code generates the value based on the static value that does not fluctuate after each retrieval. An agent can generate the value based on the real device statistical data or based on the system's statistical data, etc.

To ensure that the GET2 callback is working as expected an application can retrieve running configuration and device state information as follows:

<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <get2-leaf-list xmlns="http://yumaworks.com/ns/interfaces" />

</filter> </get> </rpc>

The server may reply with:

<rpc-reply message-id="101"

Version 19.10-12 Page 92

Page 93: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">

<get2-leaf-list xmlns="http://yumaworks.com/ns/interfaces">53</get2-leaf-list> <get2-leaf-list xmlns="http://yumaworks.com/ns/interfaces">67</get2-leaf-list> <get2-leaf-list xmlns="http://yumaworks.com/ns/interfaces">92</get2-leaf-list> </rpc-reply>

Version 19.10-12 Page 93

Page 94: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.3.3 GET2 Access Macros

GET 2 mode provides extended retrieval functionality and thus more ways to manage specific retrieval.

There are GET 2 mode specific high-level Transaction access and management utilities in ncx/getcb.h. These functions access the lower-level functions to provide simpler functions for common transaction management tasks.

The following table highlights the access macros available:

Macro Description

GETCB_GET2_TXID_STR(G) Access transaction ID as a string value.

GETCB_GET2_OBJ(G) Access object template of the value. Pointer to obj_template_t for the object being retrieved.

GETCB_GET2_TESTFN(G) Access test function that is used for filtering. Test filter function for checking nodes before processing.

GETCB_GET2_KEYQ(G) Access KeyQ. Queue of val_value_t structures representing the key leafs for the request. These are keys for the ancestor-or-self lists for this object. Fixed keys are identified using the VAL_IS_FIXED_VALUE(keyval) macro. The get2 callback must only return entries matching the provided key values. If no value is provided for a key then the first value is requested

GETCB_GET2_FIRST_KEY(G) Access macro to return the first val_value_t in the queue.

GETCB_GET2_NEXT_KEY(G,C) Access macro to return the next val_value_t in the queue.

GETCB_GET2_MATCHQ(G) Access MatchQ. Queue of val_value_t structs representing non-key leaf content-match nodes. These are always simple child nodes of the object identified by 'obj'. The content-match test is optional to implement by the get2 callback.

GETCB_GET2_FIRST_MATCH(G) Access macro to return the first val_value_t in the queue.

GETCB_GET2_NEXT_MATCH(G,C) Access macro to return the next val_value_t in the queue.

GETCB_GET2_SELECTQ(G) Access SelectQ. Q of malloced getcb_get2_select_t; 1 entry for each child select node of the object in this get2cb these select nodes only apply to the current object if the 'select_only' flag is set then this queue is used.

GETCB_GET2_FIRST_SELECT(G) Access macro to return the first getcb_get2_select_t in the queue.

GETCB_GET2_NEXT_SELECT(G,C) Access macro to return the next getcb_get2_select_t in the queue.

GETCB_GET2_RETURN_KEYQ(G) Access Return_keyQ. Queue of val_value_t structures representing the key leafs of the returned value.

GETCB_GET2_FIRST_RETURN_KEY(G) Access macro to return the first val_value_t in the queue.

GETCB_GET2_NEXT_RETURN_KEY(G,C) Access macro to return the next val_value_t in the queue.

Version 19.10-12 Page 94

Page 95: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Macro Description

GETCB_GET2_RETURN_VALQ(G) Access Return_valQ. Queue of val_value_t structures representing the non-key terminal nodes of the returned value. Only the first value is used at this time, except for leaf-list nodes. Should be empty if the 'keys-only' flag is set in the request.

GETCB_GET2_FIRST_RETURN_VAL(G) Access macro to return the first val_value_t in the queue.

GETCB_GET2_NEXT_RETURN_VAL(G,C) Access macro to return the next val_value_t in the queue.

GETCB_GET2_GETBULKQ(G) Access getbulkQ. Queue of the getcb_get2_getbulk_t structures. Set by the callback function if this is a list callback and multiple entries are returned; this is a global queue that applies to the entire response.

GETCB_GET2_FIRST_GETBULK(G) Access macro to return the first getcb_get2_getbulk_t in the queue.

GETCB_GET2_NEXT_GETBULK(G,C) Access macro to return the next getcb_get2_getbulk_t in the queue.

GETCB_GET2_CBMODE(G) Access value for the callback mode.

GETCB_GET2_MAX_ENTRIES(G) Access value for the maximum number of values to return (for getnext mode).

GETCB_GET2_MAX_LEVELS(G) Access value for the maximum depth of subtrees parameter to determine if the maximum level has been reached.

GETCB_GET2_OPER_DATA(G) Access operational data flag value. True if config=false data should be returned.

GETCB_GET2_CONFIG_DATA(G) Access configuration data flag value. True if config=true data should be returned.

GETCB_GET2_EXPAND_VAREXPR(G) Access variable expressions flag value. True is variable expressions should be expanded; false to print the variable instead.

GETCB_GET2_KEYS_ONLY(G) Access keys only flag value. True if only list keys should be returned; false for all terminal nodes.

GETCB_GET2_WITH_DEFAULTS(G) Access with-defaults flag value. True if default nodes should be returned; false if they are not requested.

GETCB_GET2_API_MODE(G) Access api mode enumeration value. The consumer walker callback API mode.

GETCB_GET2_MORE_DATA(G) Access more data flag value. Set to true if there are more instances of this object to retrieve; false otherwise.

GETCB_GET2_ACTIVE_CASE_MODNAME(G) Access active case string value. Name of the module for the module namespace of the active case; set to NULL for the same module name as the choice. Ignored unless the 'obj' type is 'choice'.

GETCB_GET2_ACTIVE_CASE(G) Access name of the active case value. Ignored unless the 'obj' type is 'choice'.

GETCB_GET2_MATCH_TEST_DONE(G) Access match test done flag value. Set to true if the get2 callback performed the request content match test(s); false if not

Version 19.10-12 Page 95

Page 96: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Macro Description

or no match tests requested.

GETCB_GET2_RETURN_VAL(G) Access in-line val_value_t to return a single leaf. Can be used instead of the return_valQ to avoid mallocing a val_value_t.

GETCB_GET2_RETURN_VAL_SET(G) Macro to test if the value is set.

GETCB_GET2_WITH_ORIGIN(G) Macro to test if the GET request is for <get-data> and the with-origin parameter is set in the client request.

GETCB_GET2_ORIGIN(G) Macro to set the return origin value for the list or presence container. Do no set for NP-container or choice. Use val_set_origin to set different origin for child nodes.

GETCB_GET2_DATASTORE(G) Macro to retrieve the NMDA datastore parameter.

GETCB_GET2_RETURN_AIOQ(G) Access return_aioQ. Queue of val_value_t structures representing the All In One returned values.

GETCB_GET2_FIRST_RETURN_AIO_VAL(G) Access macro to return the first val_value_t in the queue.

GETCB_GET2_NEXT_RETURN_AIO_VAL(C) Access macro to return the next val_value_t in the queue.

GETCB_AIO_ENCODING(G) Macro to retrieve the AIO encoding parameter.

GETCB_AIO_BUFFER(G) Macro to retrieve the AIO string buffer.

Version 19.10-12 Page 96

Page 97: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.3.4 GET2 Access Functions

GET 2 mode provides extended retrieval functionality and thus more ways to manage specific retrieval.

There are GET 2 mode specific high-level Transaction access and management utilities in ncx/getcb.h. These functions access the lower-level functions to provide simpler functions for common transaction management tasks.

The following table highlights the functions available:

API Description

getcb_add_return_val() Add a return val to a get2cb return_valQ.

getcb_find_return_val() Find a return val in the get2cb return_valQ.

getcb_find_return_val2() Find a return val in the get2cb return_valQ . Use NSID, NAME instead ofobject pointer.

getcb_find_next_return_val() Find the next matching return val in the get2cb return_valQ.

getcb_find_key() Find an input keyval in the get2cb keyQ.

getcb_find_key_str() Find an input keyval in the get2cb keyQ . USE string parameters.

getcb_find_match() Find an input keyval in the get2cb matchQ.

getcb_add_key() Add a keyval to a get2cb keyQ.

getcb_add_match() Add a match node to a get2cb matchQ.

getcb_add_select() Add a select node to a get2cb matchQ.

getcb_add_return_key() Add a return keyval to a get2cb return_keyQ .

getcb_find_return_key() Find a return keyval in the get2cb return_keyQ.

getcb_find_return_key2() Find a return keyval in the get2cb return_keyQ . Use NSID, NAME insteadof object pointer.

getcb_move_return_keys() Move the return keys to the keyQ replacing the nodes in the keyQ ifalready there.

getcb_undo_move_return_keys() Move back the return keys from the keyQ.

getcb_clean_return_data() Clean the return data in the return_val and return_valQ.

Version 19.10-12 Page 97

Page 98: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

API Description

getcb_handle_acmtest() Check the access control and testfn callback for a node that would have itskipped because the write_full_check_val function is skipped.

getcb_new_keyval() Create a new GET2 keyval holder.

getcb_new_keyval2() Create a new Get2 keyval holder using val backptr.

getcb_free_keyval() Free a GET2 keyval.

getcb_clean_keyvalQ() Free all the Get2 keyvals from a dlq_hdr.

getcb_dump_get2cb() Print the interesting fields in a get2cb.

getcb_need_get2() check if the node has a get2 callback or in a choice/case subtree that hasget2 callback.

getcb_need_get2_ex() check if the node has a get2 callback or in a choice/case subtree that hasget2 callback. Also, returns address of return choice count and top choiceobject template.

getcb_first_requested_child() Check if the specified object has any terminal nodes that need to be returnedfor a get2 request. Return the first one .

The get2cb will be examined:

- boolean flags

- select-node queue

Any content-match nodes will be returned but no filtering of these objectswill be done .

Any key leaf nodes will be skipped; Processing of key leafs is done first andis never skipped

getcb_next_requested_child() Check if the specified object has any more terminal nodes that need to bereturned for a get2 request. Return the next one

getcb_set_active_case() Set the active case to the specified object.

getcb_add_return_aioQ() Add a return val to a get2cb return_aioQ.

getcb_add_return_aio_buff() Add a return buffer as to a get2cb aio_return_buff.

Version 19.10-12 Page 98

Page 99: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.4 All In One GET2 callback

This section describes All In One (AIO) GET2 mechanism that allows to call a single GET2 callback for the whole Subtree.

AIO GET2 callbacks follow exactly the same template as regular GET2 callbacks, they use the same registration API and are getting invoked the same way for SIL and SIL-SA as regular GET2 callbacks. The main difference is that there will not be any callback invocations and there will not be any callbacks at all for any of AIO node children.

All In One GET2 support:

• Supported only for container and list nodes• YANG extension must be specified for the top AIO node• Supported for SIL and SIL-SA• Supported for XPath and Subtree filtering• Supported for RESTCONF retrieval• Supported for <get-bulk> operation• Supported for NMDA <get-data> operation for "operational" datastore• Auto-generation code support• Must be built with --sil-get2 flag during make_sil_dir_pro

The entire subtree would be expected in one retrieval in one callback invocation. That’s if the callback is registered for a container, any complex nodes within this container will not have any extra callbacks, they will be handled by the top AIO container callback.

With help of a new YANG extension, the server will set specific flags to the objects to identify them as a special case retrieval. This extension would be used in a container or a list to force the server to treat that data subtree as a AIO node forGET2.

The yangdump auto-generation code does not auto generate callbacks for children of the top All In One parent. The callbacks will be generated only for the top nodes that have the extension specified. The extension definition looks as follows:

extension sil-aio-get2 { description "Used within a data definition statement to define the GET2 retrieval mechanism. This extension affects the descendant data nodes.

This extension can be used in a container or list to force the server to treat that data subtree as a terminal node for GET2.

The entire subtree would be expected in one retrieval in one callback invocation.

The entire subtree can be specified in the JSON or XML buffer that will be used for return values. The server will parse and handle the buffer and process retrieval based on the provide JSON or XML encoded buffer.

The 'parmstr' argument can specify the encoding that will be used in the callback. Available options are: - xml - json

If not specified default val value retrieval mechanism

Version 19.10-12 Page 99

Page 100: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

will be assumed. "; argument parmstr; }

As an example, to illustrate how the extension can be used in a YANG module refer to the following snippet from YANG module:

get3-test.yang

/* All in One callback within config true and GET2 reg callbacks */ container get3-config-cont { presence "Presence container";

list config-list { key name; leaf name { type string; }

list nonconfig-list { // Regular GET2 CB config false; key name; leaf name { type string; }

list nonconfig-list2 { // All in One GET2 CB ywx:sil-aio-get2;

key name; leaf name { type string; }

list nonconfig-list3 { // No callback key name; leaf name { type string; }

container int-con { // No callback leaf int-con-leaf { type int32; } } } } } } }

Example C file:

Refer to the SIL-SA file /usr/share/yumapro/src/get3-test/src/get3-test.c

Refer to the SIL file /usr/share/yumapro/src/get3-test-local/src/get3-test.c

In the YANG module example above we define top level configuration parent and next regular GET2 child and then the All In One GET2 list child.

In this case the server will invoke GET2 callbacks only for "nonconfig-list" first and then for AIO "nonconfig-list2" list and will not invoke any deeper level callbacks. The server will expect that the AIO "nonconfig-list2" callback will supply

Version 19.10-12 Page 100

Page 101: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

the GET2 control block with the sufficient information about "nonconfig-list2" node children, complex children as well as terminal nodes.

5.4.1 All In One List Example

This section illustrates how to use All In One GET2 callbacks for list nodes. Assume we have the same data model as described above then the GET2 callback may look as follow:

/********************************************************************* FUNCTION get_test_cont_list_list** Get database object callback for list nonconfig-list2* Path: /get3-nonconfig-cont/nonconfig-list/nonconfig-list2* Fill in 'get2cb' response fields** sil-aio-get2 extension enabled for this object;* No callbacks for children will be called** INPUTS:* see ncx/getcb.h for details (getcb_fn2_t)** RETURNS:* error status********************************************************************/static status_t get_test_cont_list_list (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb){ obj_template_t *obj = GETCB_GET2_OBJ(get2cb); status_t res = NO_ERR;

/* create 3 top level lists */ uint32 key = 0; for (key = 1; key < 4; key++) {

const xmlChar *key1 = NULL; if (key == (uint32)1) { key1 = (const xmlChar *)"name1"; } else if (key == (uint32)2) { key1 = (const xmlChar *)"name2"; } else if (key == (uint32)3) { key1 = (const xmlChar *)"name3"; }

/* make return value that will be added to the return_aioQ */ val_value_t *retval = val_new_value(); if (!retval) { return ERR_INTERNAL_MEM; } val_init_from_template(retval, obj);

/* Use retval for the current callback obj and fill * it in with folowing terminal and complex nodes; * then add to get2cb with help of getcb_add_return_aioQ API */ obj_template_t *childobj =

Version 19.10-12 Page 101

Page 102: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

getcb_first_requested_child(get2cb, obj); for (; childobj; childobj = getcb_next_requested_child(get2cb, childobj)) {

const xmlChar *name = obj_get_name(childobj);

/* Retrieve the value of this child node and * add it to retval of the current callback node */ if (!xml_strcmp(name, (const xmlChar *)"name")) { /* leaf name (string) */ val_value_t *child = val_make_simval_obj(childobj, key1, &res); if (child) { res = val_child_add(child, retval); if (res != NO_ERR) { val_free_value(child); val_free_value(retval); return ERR_NCX_INVALID_VALUE; } } else { val_free_value(retval); return ERR_NCX_INVALID_VALUE; } } else if (!xml_strcmp(name, (const xmlChar *)"nonconfig-list3")) {

/* list nonconfig-list (list) */ uint32 nextlist_key = 0; for (nextlist_key = 1; nextlist_key < 3; nextlist_key++) {

const xmlChar *keyname = NULL; if (nextlist_key == (uint32)1) { keyname = (const xmlChar *)"name1"; } else if (nextlist_key == (uint32)2) { keyname = (const xmlChar *)"name2"; }

/* create 5 list entries */ val_value_t *listval = create_list_entry(childobj, (const xmlChar *)"name", keyname, &res); if (!listval) { val_free_value(retval); return ERR_INTERNAL_MEM; }

/* Use add_force to allow insertion lists with NO keys */ res = val_child_add(listval, retval); if (res != NO_ERR) { val_free_value(listval); val_free_value(retval); return ERR_NCX_INVALID_VALUE; } } } }

if (res == NO_ERR) { /* generate the internal index Q chain */

Version 19.10-12 Page 102

Page 103: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

res = val_gen_index_chain(obj, retval); if (res != NO_ERR) { val_free_value(retval); return res; } }

/* Ensure that the generated value is correct and can be added * to the return Queue. */ if (retval && res == NO_ERR) { res = val_validate_value(retval); if (res != NO_ERR) { val_free_value(retval); return res; } }

/* Add created val_value_t to get2cb with help of * getcb_add_return_aioQ API; In case of list callbacks, * repeat above steps for another list entry */ getcb_add_return_aioQ(get2cb, retval); }

return res;

} /* get_test_cont_list_list */

In the examples above we used a function "create_list_entry" that is a custom function that can be used as an example function that helps to build the subtree data. This is not a server API and used in this article just to demonstrate how the children nodes can be constructed. For more example you can refer to following articles:

Below is the example function that was used in he above AIO callback example:

/********************************************************************* FUNCTION create_list_entry** Make a list entry based on the key** INPUTS:* res = return status** RETURNS:* val_value_t of listval entry if no error* else NULL**********************************************************************/static val_value_t * create_list_entry (obj_template_t *list_obj, const xmlChar *keyname, const xmlChar *keystr, status_t *res){ /* find a key child obejct */ obj_template_t *key_obj = obj_find_child(list_obj, GET3_TEST_MOD,

Version 19.10-12 Page 103

Page 104: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

keyname); if (!key_obj) { *res = ERR_NCX_INVALID_VALUE; return NULL; }

val_value_t *list_value = val_new_value(); if (!list_value) { *res = ERR_NCX_INVALID_VALUE; return NULL; } val_init_from_template(list_value, list_obj);

/* make key leaf entry */ val_value_t *child = val_make_simval_obj(key_obj, keystr, res); if (!child) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; }

*res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); val_free_value(list_value); return NULL; }

obj_template_t *notkey_obj = obj_find_child(list_obj, GET3_TEST_MOD, (const xmlChar *)"not-keyname"); if (notkey_obj) { /* make NON key leaf entry */ child = val_make_simval_obj(notkey_obj, (const xmlChar *)"some-value", res); if (!child) { *res = ERR_NCX_INVALID_VALUE; }

if (*res == NO_ERR) { *res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); } } }

obj_template_t *cont_obj = obj_find_child(list_obj, GET3_TEST_MOD, (const xmlChar *)"int-con"); if (cont_obj) { /* make return value that will be added to the return_aioQ */ val_value_t *contval = val_new_value(); if (!contval) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE;

Version 19.10-12 Page 104

Page 105: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

return NULL; } val_init_from_template(contval, cont_obj);

obj_template_t *leaf_obj = obj_find_child(cont_obj, GET3_TEST_MOD, (const xmlChar *)"con-leaf"); if (leaf_obj) { val_value_t *leafval = val_make_simval_obj(leaf_obj, (const xmlChar *)"42", res); if (leafval) { *res = val_child_add(leafval, contval); if (*res != NO_ERR) { val_free_value(leafval); val_free_value(contval); } } else { val_free_value(contval); *res = ERR_NCX_INVALID_VALUE; }

if (*res == NO_ERR) { *res = val_child_add(contval, list_value); if (*res != NO_ERR) { val_free_value(contval); } } } else { val_free_value(contval); } }

/* generate the internal index Q chain */ *res = val_gen_index_chain(list_obj, list_value); if (*res != NO_ERR) { log_error("\nError: could not generate index chain (%s)", get_error_string(*res)); val_free_value(list_value); return NULL; }

return list_value;

} /* create_list_entry */

The following section in the AIO callback function example is used to ensure that the constructed value is well-formed and can be safely used by the server. It runs simple sanity check to verify that if the value is a list it has all the keys setup. It checks descendant-or-self nodes for lists. Checks if they have index chains built already. If not, then try to add one for each of the key objects in order.

If the value is not a container or a list or if the list value index chain is malformed this function will return an error "invalid value".

/* Ensure that the generated value is correct and can be added * to the return Queue.

Version 19.10-12 Page 105

Page 106: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

*/ if (retval && res == NO_ERR) { res = val_validate_value(retval); if (res != NO_ERR) { val_free_value(retval); return res; } }

The below section of the AIO callback is used to add a new val value into the Queue that will be used as a return values of the callbacks. That will be used later for processing, for filtering, for other manipulations:

/* Add created val_value_t to get2cb with help of * getcb_add_return_aioQ API; In case of list callbacks, * repeat above steps for another list entry */ getcb_add_return_aioQ(get2cb, retval);

5.4.2 All In One Container Example

This section illustrates how to use All In One GET2 callbacks for container nodes. Assume we have the following data model:

/* All in One callback within config true NP-container */ container get3-config-cont {

/* NP-container with a terminal node */ container nonconfig-NPcont { // All in One get2 CB ywx:sil-aio-get2; config false;

list nonconfig-list { // No callback key name; leaf name { type string; } } leaf D { type int8; } } }

Then the AIO GET2 callback may look as follow:

/********************************************************************* FUNCTION get_test_config_cont_nonconfig_NPcont** Get database object callback for container nonconfig-NPcont* Path: /get3-config-cont/nonconfig-NPcont

Version 19.10-12 Page 106

Page 107: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* Fill in 'get2cb' response fields** sil-aio-get2 extension enabled for this object;* No callbacks for children will be called** INPUTS:* see ncx/getcb.h for details (getcb_fn2_t)** RETURNS:* error status********************************************************************/static status_t get_test_config_cont_nonconfig_NPcont (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb){ /* an NP container always exists so no test for node_exists * by the SIL or SIL-SA callback is needed */ obj_template_t *obj = GETCB_GET2_OBJ(get2cb); status_t res = NO_ERR;

/* make return value that will be added to the return_aioQ */ val_value_t *retval = val_new_value(); if (!retval) { return ERR_INTERNAL_MEM; } val_init_from_template(retval, obj);

/* Use retval for the current callback obj and fill * it in with folowing terminal and complex nodes; * then add to get2cb with help of getcb_add_return_aioQ API */ obj_template_t *childobj = getcb_first_requested_child(get2cb, obj); for (; childobj; childobj = getcb_next_requested_child(get2cb, childobj)) {

const xmlChar *name = obj_get_name(childobj);

/* Retrieve the value of this child node and * add it to retval of the current callback node */ if (!xml_strcmp(name, (const xmlChar *)"nonconfig-list")) { /* list nonconfig-list (list) */

uint32 key = 0; for (key = 1; key < 3; key++) {

/* create 2 list entries */ const xmlChar *keyname = NULL; if (key == (uint32)1) { keyname = (const xmlChar *)"name1"; } else if (key == (uint32)2) { keyname = (const xmlChar *)"name2"; }

val_value_t *listval = create_list_entry(childobj, (const xmlChar *)"name", keyname, &res); if (!listval) {

Version 19.10-12 Page 107

Page 108: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_free_value(retval); return ERR_INTERNAL_MEM; }

/* Use add_force to allow insertion lists with NO keys */ res = val_child_add(listval, retval); if (res != NO_ERR) { val_free_value(listval); val_free_value(retval); return ERR_NCX_INVALID_VALUE; } } } else if (!xml_strcmp(name, (const xmlChar *)"D")) { /* leaf D (int8) */ val_value_t *child = val_make_simval_obj(childobj, (const xmlChar *)"42", &res); if (child) { res = val_child_add(child, retval); if (res != NO_ERR) { val_free_value(child); val_free_value(retval); return ERR_NCX_INVALID_VALUE; } } else { val_free_value(retval); return ERR_NCX_INVALID_VALUE; } } }

/* Ensure that the generated value is correct and can be added * to the return Queue. */ if (retval && res == NO_ERR) { res = val_validate_value(retval); if (res != NO_ERR) { val_free_value(retval); return res; } }

/* Add created val_value_t to get2cb with help of * getcb_add_return_aioQ API; In case of list callbacks, * repeat above steps for another list entry */ getcb_add_return_aioQ(get2cb, retval);

return res;

} /* get_test_config_cont_nonconfig_NPcont */

In the examples above we used a function "create_list_entry" that is a custom function that can be used as an example function that helps to build the subtree data. This is not a server API and used in this article just to demonstrate how the children nodes can be constructed. For more example you can refer to following articles:

Below is the example function that was used in he above AIO callback example:

Version 19.10-12 Page 108

Page 109: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/********************************************************************* FUNCTION create_list_entry** Make a list entry based on the key** INPUTS:* res = return status** RETURNS:* val_value_t of listval entry if no error* else NULL**********************************************************************/static val_value_t * create_list_entry (obj_template_t *list_obj, const xmlChar *keyname, const xmlChar *keystr, status_t *res){ /* find a key child obejct */ obj_template_t *key_obj = obj_find_child(list_obj, GET3_TEST_MOD, keyname); if (!key_obj) { *res = ERR_NCX_INVALID_VALUE; return NULL; }

val_value_t *list_value = val_new_value(); if (!list_value) { *res = ERR_NCX_INVALID_VALUE; return NULL; } val_init_from_template(list_value, list_obj);

/* make key leaf entry */ val_value_t *child = val_make_simval_obj(key_obj, keystr, res); if (!child) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; }

*res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); val_free_value(list_value); return NULL; }

obj_template_t *notkey_obj = obj_find_child(list_obj, GET3_TEST_MOD, (const xmlChar *)"not-keyname"); if (notkey_obj) { /* make NON key leaf entry */ child = val_make_simval_obj(notkey_obj,

Version 19.10-12 Page 109

Page 110: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

(const xmlChar *)"some-value", res); if (!child) { *res = ERR_NCX_INVALID_VALUE; }

if (*res == NO_ERR) { *res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); } } }

obj_template_t *cont_obj = obj_find_child(list_obj, GET3_TEST_MOD, (const xmlChar *)"int-con"); if (cont_obj) { /* make return value that will be added to the return_aioQ */ val_value_t *contval = val_new_value(); if (!contval) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; } val_init_from_template(contval, cont_obj);

obj_template_t *leaf_obj = obj_find_child(cont_obj, GET3_TEST_MOD, (const xmlChar *)"con-leaf"); if (leaf_obj) { val_value_t *leafval = val_make_simval_obj(leaf_obj, (const xmlChar *)"42", res); if (leafval) { *res = val_child_add(leafval, contval); if (*res != NO_ERR) { val_free_value(leafval); val_free_value(contval); } } else { val_free_value(contval); *res = ERR_NCX_INVALID_VALUE; }

if (*res == NO_ERR) { *res = val_child_add(contval, list_value); if (*res != NO_ERR) { val_free_value(contval); } } } else { val_free_value(contval); } }

/* generate the internal index Q chain */ *res = val_gen_index_chain(list_obj, list_value); if (*res != NO_ERR) { log_error("\nError: could not generate index chain (%s)",

Version 19.10-12 Page 110

Page 111: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

get_error_string(*res)); val_free_value(list_value); return NULL; }

return list_value;

} /* create_list_entry */

The following section in the AIO callback function example is used to ensure that the constructed value is well-formed and can be safely used by the server. It runs simple sanity check to verify that if the value is a list it has all the keys setup. It checks descendant-or-self nodes for lists. Checks if they have index chains built already. If not, then try to add one for each of the key objects in order.

If the value is not a container or a list or if the list value index chain is malformed this function will return an error "invalidvalue".

/* Ensure that the generated value is correct and can be added * to the return Queue. */ if (retval && res == NO_ERR) { res = val_validate_value(retval); if (res != NO_ERR) { val_free_value(retval); return res; } }

The below section of the AIO callback is used to add a new val value into the Queue that will be used as a return values of the callbacks. That will be used later for processing, for filtering, for other manipulations:

/* Add created val_value_t to get2cb with help of * getcb_add_return_aioQ API; In case of list callbacks, * repeat above steps for another list entry */ getcb_add_return_aioQ(get2cb, retval);

Version 19.10-12 Page 111

Page 112: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.4.3 All In One GET2 Callbacks with XML/JSON buffers

AIO GET2 callbacks follow exactly the same template as regular GET2 callbacks, they use the same registration API and are getting invoked the same way for SIL and SIL-SA as regular GET2 callbacks. The main difference is that there will not be any callback invocations for descendant children and there will not be any callbacks auto generated at all for any of AIOnode children.

Let us go through simple examples that will illustrate how to utilize the AIO callbacks for the specific purposes. First we need a YANG module. Consider this simplified, but functional, example. You can download this YANG module from attachments and run make_sil_dir_pro to auto-generate stub SIL code for this module.

Note, the AIO callback is not part of the auto-generated code by default and you will have to add an extension to the desired node that you want to become an AIO callback node. Otherwise, the auto generated code will generate regular GET2 callback for that node(s).

In this example we are going to use "sil-aio-get2" extension with 'xml' and "json" parameters, meaning we are going to use XML and JSON buffers as a return values in the AIO callback.

As an example, to illustrate how the "sil-aio-get2" extension can be used in a YANG module refer to the following YANG module:

module aio-test { namespace "http://yumaworks.com/ns/aio-test"; prefix "aiotest";

import yumaworks-extensions { prefix ywx; }

revision 2020-02-20 { description "Initial Version"; }

/* All in One callback within config true and GET2 reg callbacks */ container get3-config-cont { presence "Presence container";

list config-list { key name; leaf name { type string; }

list nonconfig-list { // Regular GET2 CB config false; key name; leaf name { type string; }

list nonconfig-list2 { // All in One XML GET2 CB ywx:sil-aio-get2 "xml";

key name; leaf name { type string; }

list nonconfig-list3 { // No callback key name; leaf name { type string; } leaf not-keyname { type string; }

container int-con { // No callback leaf con-leaf { type int32; }

Version 19.10-12 Page 112

Page 113: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

} } } } } }

/* All in One callback within config true NP-container */ container get3-state-cont { // All in One get2 CB JSON ywx:sil-aio-get2 "json"; config false;

leaf D { type int8; }

choice thing-choice { // No callback case A { leaf A1 { type string; } leaf A2 { type string; } } case B { leaf B3 { type string; } leaf B2 { type string; } } case C { // active case leaf C1 {type string; } leaf C2 {type string; } } } }}

AIO XML Callback example

In the YANG module example above we define top level configuration parent "get3-config-cont/config-list" and next regular GET2 child "nonconfig-list" and then the AIO GET2 list child "nonconfig-list2" with XML parameter in the extension.

In this case the server will invoke GET2 callbacks only for "nonconfig-list" and then for AIO "nonconfig-list2" list and will not invoke any descendant level callbacks. The server will expect that the AIO "nonconfig-list2" callback will supply well formed XML buffer to the GET2 control block.

NOTE: if the callback target is a list, the XML buffer must provide parent node in the buffer. If the list is a top level node use the following wrapper:

<config xmlns=\"http://netconfcentral.org/ns/yuma-ncx\"></config>

There cannot be multiple siblings in XML, it will make XML malformed and the server will not be able to parse this buffer and will return an error. As a result the server will skip over this callback nodes in the output and will not generate any output for them.

Version 19.10-12 Page 113

Page 114: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The AIO GET2 callback may look as follow for the "/get3-config-cont/config-list/nonconfig-list/nonconfig-list2" list.

/********************************************************************* FUNCTION aio_test_get3_config_cont_config_list_nonconfig_list_nonconfig_list2_get** Get database object callback for list nonconfig-list2* Path: list /get3-config-cont/config-list/nonconfig-list/nonconfig-list2* Fill in 'get2cb' response fields** sil-aio-get2 extension enabled for this object;* No callbacks for children will be called** XML encoded buffer is expected** INPUTS:* see ncx/getcb.h for details (getcb_fn2_t)** RETURNS:* error status********************************************************************/static status_t aio_test_get3_config_cont_config_list_nonconfig_list_nonconfig_list2_get ( ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb){ if (LOGDEBUG) { log_debug("\nEnter aio_test_get3_config_cont_config_list_nonconfig_list_nonconfig_list2_get"); }

(void)scb; (void)msg;

status_t res = NO_ERR;

/* make XML buffer that will be used instead of return val value * NOTE if the callback target is a list, the XML buffer must provide * parent node in the buffer. There cannot be multiple siblings * in XML, it will make XML malformed. * * If the list is a top level node use the following wrapper: * <config xmlns=\"http://netconfcentral.org/ns/yuma-ncx\"></config> */ const xmlChar *xml_buffer = (const xmlChar *) "<nonconfig-list xmlns=\"http://yumaworks.com/ns/aio-test\">" "<nonconfig-list2>" "<name>name1</name><nonconfig-list3>" "<name>name1</name></nonconfig-list3><nonconfig-list3>" "<name>name2</name></nonconfig-list3></nonconfig-list2>" "<nonconfig-list2>" "<name>name2</name><nonconfig-list3>" "<name>name1</name></nonconfig-list3><nonconfig-list3>" "<name>name2</name></nonconfig-list3></nonconfig-list2>" "<nonconfig-list2>" "<name>name3</name><nonconfig-list3>" "<name>name1</name></nonconfig-list3><nonconfig-list3>" "<name>name2</name></nonconfig-list3></nonconfig-list2>" "</nonconfig-list>";

Version 19.10-12 Page 114

Page 115: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* Add created buffer to return get2cb */ res = getcb_add_return_aio_buff(get2cb, xml_buffer);

return res;

} /* aio_test_get3_config_cont_config_list_nonconfig_list_nonconfig_list2_get */

AIO JSON Callback Examples

A JSON example will be similar to the above XML example, it will use the same API, however instead of using XML buffer the callback will provide JSON buffer to the server.

Assume the same YANG module example above we define top level AIO JSON container "get3-state-cont".

In this case the server will invoke AIO JSON callback for "get3-state-cont" container and will not invoke any descendant level callbacks. The server will expect that the AIO JSON "get3-state-cont" callback will supply the GET2 control block with well formed JSON buffer that will be used as a return value for the callback.

The AIO JSON GET2 callback may look as follow for the "get3-state-cont" container.

/********************************************************************* FUNCTION aio_test_get3_state_cont_get** Get database object callback for container get3-state-cont* Path: container /get3-state-cont* Fill in 'get2cb' response fields** sil-aio-get2 extension enabled for this object;* No callbacks for children will be called** JSON encoded buffer is expected** INPUTS:* see ncx/getcb.h for details (getcb_fn2_t)** RETURNS:* error status********************************************************************/static status_t aio_test_get3_state_cont_get (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb){ if (LOGDEBUG) { log_debug("\nEnter aio_test_get3_state_cont_get"); }

(void)scb; (void)msg;

status_t res = NO_ERR;

/* make JSON buffer that will be used instead of return val value */ const xmlChar *json_buffer = (const xmlChar *) "{\"aio-test:get3-state-cont\":{\"D\":42,\"C2\":\"someleaf\"}}";;

/* Add created buffer to return get2cb */

Version 19.10-12 Page 115

Page 116: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

res = getcb_add_return_aio_buff(get2cb, json_buffer);

return res;

} /* aio_test_get3_state_cont_get */

As a result, whenever some north bound agent trying to retrieve the list or container that we have AIO callbacks registered, the callback is invoked and a client gets all the values that AIO callbacks returns.

To ensure that the buffer returned by AIO callback was successfully consumed by the server an application can retrieve operational datastore with help of the following operation as an example. Assume, we already created parent configuration nodes.

<get> <filter type="subtree"> <get3-config-cont xmlns="http://yumaworks.com/ns/aio-test"/> </filter> </get>

The server should reply with:

<data> <get3-config-cont xmlns="http://yumaworks.com/ns/aio-test"> <config-list> <name>list1</name> <nonconfig-list> <name>name1</name> <nonconfig-list2> <name>name1</name> <nonconfig-list3> <name>name1</name> </nonconfig-list3> <nonconfig-list3> <name>name2</name> </nonconfig-list3> </nonconfig-list2> <nonconfig-list2> <name>name2</name> <nonconfig-list3> <name>name1</name> </nonconfig-list3> <nonconfig-list3> <name>name2</name> </nonconfig-list3> </nonconfig-list2> <nonconfig-list2> <name>name3</name> <nonconfig-list3> <name>name1</name> </nonconfig-list3> <nonconfig-list3> <name>name2</name> </nonconfig-list3>

Version 19.10-12 Page 116

Page 117: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

</nonconfig-list2> </nonconfig-list> </config-list> </get3-config-cont> </data>

Or, for example, if we want to retrieve a node that was generated by AIO JSON callback, a client may send the following <get> request:

<get> <filter type="subtree"> <get3-state-cont xmlns="http://yumaworks.com/ns/aio-test"/> </filter> </get>

The server should reply with:

<data> <get3-state-cont xmlns="http://yumaworks.com/ns/aio-test"> <D>42</D> <C2>someleaf</C2> </get3-state-cont> </data>

Version 19.10-12 Page 117

Page 118: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.5 User Defined Data Types

User defined data types are supported with callback functions that apply to all YANG leaf or leaf-list nodes using a specific data type.

There are 3 types of callbacks supported to allow customization of YANG data types:

• validate: custom validation function, used when a data node is set

• canonical: convert a value to canonical format, used when a data node is set

• compare: compare 2 values of the same data type, used when a data node is set

There are several standard YANG data types that are supported with built-in canonical functions, which can be found in ncx/ipaddr_typ.c (if sources are available). The server will automatically check for validate and canonical callbacks when a data node is parsed from XML or JSON input. The automatic canonical check can be disabled using the with-canonical” CLI parameter.

leaf with-canonical { description "If set to 'true', then the server will automatically convert XML and JSON input parameters to the canonical format for the YANG data type, if possible.

The following built-in YANG data types are affected: - ipv6-address - ipv6-address-no-zone - domain-name - phys-address - mac-address - hex-string - uuid

Any canonical callbacks for user-defined data types are also affected by this parameter.

Internal values can be manually converted to canonical format using the val_set_canonical API. "; type boolean; default true; }

Version 19.10-12 Page 118

Page 119: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.5.1 Callback Registration

A user defined type is registered with the function typ_userdef_register. This must be done after the YANG module containing the typedef statement has been loaded. Only top-level typedefs can be supported. Typedefs within groupings or nested within containers or lists cannot be supported.

/********************************************************************* FUNCTION typ_userdef_register** Register the callback functions for a user defined type* At least one callback needs to be set in order for this* userdef type to have any affect** INPUTS:* modname == module name defining the type* typname == name of the type* validate_fn == validate callback (may be NULL)* canonical_fn == canonical callback (may be NULL)* compare_fn == compare callback (may be NULL)* cookie == cookie to pass to callback function* RETURNS:* status*********************************************************************/extern status_t typ_userdef_register (const xmlChar *modname, const xmlChar *typname, typ_validate_fn_t validate_fn, typ_canonical_fn_t canonical_fn, typ_compare_fn_t compare_fn, void *cookie);

Parameters:

• modname: module name containing the typedef (mandatory)

• typname: type name (mandatory)

• validate_fn: validation callback (optional)

• canonical_fn: canonical callback (optional)

• compare_fn: compare callback (optional)

• cookie: pointer that will be passed to callback (optional)

Example:

/* ietf-inet-types:ipv6-address */ status_t res = typ_userdef_register((const xmlChar *)”ietf-inet-types”, (const xmlChar *)"ipv6-address", NULL, // validate_fn

Version 19.10-12 Page 119

Page 120: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

ipv6_address_canonical_fn, NULL, // compare_fn NULL); // cookie if (res != NO_ERR) { return res; }

Version 19.10-12 Page 120

Page 121: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.5.2 typ_validate_fn_t

The validate callback is used for special custom validation of values conforming to a YANG data type.

This function returns NO_ERR even if it does not do any validation.

It returns an error code if validation fails.

/* userdef validate callback function * * user validation callback for a userdef type * INPUTS: * typdef == type definition for the user defined type * inval == input value to convert * cookie == cookie value passed to register function * RETURNS: * the validation status */typedef status_t (*typ_validate_fn_t) (typ_def_t *typdef, val_value_t *val, void *cookie);

Parameters:

• typdef: internal type definition control block for the data type being validated

• val: value structure containing the value to be validated

• cookie: cookie pointer passed to registration function

Example:

/********************************************************************* FUNCTION admin_validate_fn** validate callback for an administrative string** INPUTS:* typdef == type definition for the user defined type* val == input value to validate* cookie == cookie value passed to register function* RETURNS:* status*/static status_t admin_validate_fn (typ_def_t *typdef, val_value_t *val, void *cookie){ (void)typdef; (void)cookie;

Version 19.10-12 Page 121

Page 122: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

if (VAL_TYPE(val) != NCX_BT_STRING) { return ERR_NCX_OPERATION_FAILED; }

const xmlChar *valstr = val->v.str; if (valstr == NULL) { return NO_ERR; }

/* check if the string passes admin format checks */ if (check_admin_string_ok(valstr)) { return NO_ERR; } return ERR_NCX_INVALID_VALUE;

} /* admin_validate_fn */

Version 19.10-12 Page 122

Page 123: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.5.3 typ_canonical_fn_t

The canonical callback is used to convert a data node value to the canonical format for the data type. This is important for list key leafs, or else different representations of the same value (e.g. ipv6-address) will be treated as separate list entries.

This function returns NO_ERR even if it does not do any conversion to canonical format.

It returns an error code if some error occurs and conversion to canonical format fails.

/* userdef canonical callback function * * convert the inval to the canonical format for the type * INPUTS: * typdef == type definition for the user defined type * val == input value to convert * cookie == cookie value passed to register function * OUTPUTS: * val == can be converted to canonical format * RETURNS: * status */typedef status_t (*typ_canonical_fn_t) (typ_def_t *typdef, val_value_t *val, void *cookie);

Parameters:

• typdef: internal type definition control block for the data type being converted

• val: value structure containing the value to be converted in place to canonical format

• cookie: cookie pointer passed to registration function

Example:

/********************************************************************* FUNCTION lowercase_canonical_fn* <generic convert to lowercase>* canonical callback for a domain name string* convert the inval to the canonical format for the type* INPUTS:* typdef == type definition for the user defined type* val == input value to convert* cookie == cookie value passed to register function* OUTPUTS:* val == can be changed to canonical format* RETURNS:* status*/static status_t lowercase_canonical_fn (typ_def_t *typdef, val_value_t *val, void *cookie)

Version 19.10-12 Page 123

Page 124: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

{ (void)typdef; (void)cookie;

if (VAL_TYPE(val) != NCX_BT_STRING) { return ERR_NCX_OPERATION_FAILED; }

xmlChar *valstr = VAL_STRING(val); if (valstr == NULL) { return NO_ERR; }

/* convert the string to lowercase in place */ xmlChar *p = valstr; while (*p) { *p = (xmlChar)tolower((int)*p); }

return NO_ERR;

} /* lowercase_canonical_fn */

Version 19.10-12 Page 124

Page 125: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

5.5.4 typ_compare_fn_t

The compare callback is used to compare two values of the same data type. It is used in the val_compare functions. The standard compare function will skipped if this callback is present for the data type. This function is only needed if the standard compare function for the data type is not correct for some reason (E.g: a vendor-specific structured string).

This function returns NO_ERR if the comparison is done and no need to do the standard compare.

This function returns ERR_NCX_SKIPPED if the comparison is not done so the standard compare function needs to be invoked.

This function returns some error code if an error occurs while attempting the comparison (e.g. ERR_INTERNAL_MEM ifa malloc fails)

/* userdef compare callback function * * compare 2 val_value_t nodes of the same user defined type * INPUTS: * typdef == type definition for the user defined type * val1 == input value 1 to comapre * val2 == input value 2 to comapre * cookie == cookie value passed to register function * retval == address of return compare value * OUTPUTS: * *retval == return compare value * RETURNS: * status (ERR_NCX_SKIPPED if no compare done) */typedef status_t (*typ_compare_fn_t) (const typ_def_t *typdef, const val_value_t *val1, const val_value_t *val2, void *cookie, int *retval);

Parameters:

• typdef: internal type definition control block for the data type being compared

• val1:one of the values to compare

• val2:one of the values to compare

• cookie: cookie pointer passed to registration function

• retval: pointer to compare result value (set to -1, 0, or 1) if return value is NO_ERR

Example:

* compare 2 val_value_t nodes of the same user defined type * INPUTS: * typdef == type definition for the user defined type * val1 == input value 1 to comapre * val2 == input value 2 to comapre * cookie == cookie value passed to register function

Version 19.10-12 Page 125

Page 126: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* retval == address of return compare value * OUTPUTS: * *retval == return compare value * RETURNS: * status (ERR_NCX_SKIPPED if no compare done) */static status_t admin_compare_fn (typ_def_t *typdef, const val_value_t *val1, const val_value_t *val2, void *cookie, int *retval){ (void)typdef; (void)cookie;

if (VAL_TYPE(val1) != NCX_BT_STRING) { return ERR_NCX_OPERATION_FAILED; }

if (VAL_TYPE(val12) != NCX_BT_STRING) { return ERR_NCX_OPERATION_FAILED; }

const xmlChar *val1str = VAL_STRING(val1); if (val1str == NULL) { return ERR_NCX_SKIPPED; }

const xmlChar *val2str = VAL_STRING(val2); if (val2str == NULL) { return ERR_NCX_SKIPPED; }

/* compare as case-insensitive strings */ int ret = strcasecmp(const char *)val1str, (const char *)val2str); *retval = ret; return NO_ERR;

} /* admin_compare_fn */

Version 19.10-12 Page 126

Page 127: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6 In-Transaction CallbacksIn-transaction capabilities are being added to the netconfd-pro server API to allow an application to update the configuration data and perform additional actions while the transaction is in progress. This can be a vital solution to implement many services in switch/router management operations.

The netconfd-pro server uses 3 phases database editing model with In-Transaction APIs, as defined in section 6 of the YumaPro Developer Manual.

• Validate phase

• Apply phase

• Commit or rollback phase

However, this model is enhanced with callbacks and validation mechanism to support all the In-Transactions APIs. The following diagram illustrates what callbacks are invoked and when to expect them to be invoked during the transaction.

The following callback APIs are supported:

• Set Hook: Similar to the EDIT-1 or EDIT-2 callbacks, except this callback is only invoked once at the start of the edit for a particular data node. This callback can alter the data in the current edit and also add new edits to the current transaction. This callback will be invoked before EDIT-1 or EDIT-2 callbacks for the same object.

Version 19.10-12 Page 127

Page 128: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

• Post Set Hook: Similar to the Set Hook callback except that it is invoked when an object is modified but AFTER EDIT callback is done for the same object. When the netconfd-pro server has been configured to provide a candidate configuration, Post Set Hook code will be invoked when changes are done to the <candidate> configuration if the --target=candidate parameter is used. If --target=running then the Post Set Hook will be invoked at the start of the transaction on the <running> datastore. This callback will be invoked AFTER a EDIT-1 or EDIT-2 callback for the same object.

• Transaction Hook: Similar to the Set Hook callback except this callback is invoked just before the data is committed to the running datastore. This callback will be invoked after EDIT-1 or EDIT-2 callbacks for the same object.

• Transaction Start: The callback that is intended to provide access to the transaction control block and its parameters right before the transaction is started.

• Transaction Complete: The callback that is intended to provide access to the transaction control block and its parameters right after the transaction is completed. Called for every transaction completion, not just transactions that complete without errors.

• Validate Complete: The callback is intended to allow manipulations with the running and candidate configurations(equivalent to completion of validation phase during <commit>).

• Apply Complete: The callback is intended to allow manipulations with the running and candidate configurations (equivalent to completion of apply phase during <commit>).

• Commit Complete: The callback is a user/system callback that is invoked when the <commit> operation completes without errors or the internal <replay-config> operation completes without errors.

• Rollback Complete: The callback is the user/system callback that is invoked after and if the Rollback Phase has been processed during the <commit> operation.

• Set Order Hook: Set the secondary SIL priority for instances of the same list object that is being set in the same edit. This allows the instance SIL callback order to be set in addition to the object priority.

The following API functions are supported that can be called from the Set Hook, EDIT-1 or EDIT-2 callbacks:

• Add Edit (agt_val_add_edit): Add an edit operation to the current transaction

• Get Data (agt_val_get_data): Retrieve an instance of a data node from the server.

The netconfd-pro provides the following SIL-SA support for In-Transaction APIs:

• SA Transaction Start: The callback that is intended to provide access to the transaction control block and its parameters right before the transaction is started. For SIL-SA usage the server does not provide transaction control block, instead it passes the transaction ID for reference and some crucial information about the transaction, such as the information about whether the current transaction is for the running datastore, is the transaction for validate operation, or if it is for Rollback Phase.

• SA Transaction Complete: The callback that is intended to provide access to the transaction control block and its parameters right after the transaction is completed. Called for every transaction completion, not just transactions that complete without errors. For SIL-SA usage the server does not provide transaction control block, instead it passes only the transaction ID for reference.

If an application needs to write more data in the datastore in the same transaction, there are mechanisms implemented in theform of API functions called Set Hook and Post Set Hook.

The Set Hook and Post Set Hook callbacks are the ways for the application to manipulate with the datastore in the same transaction. For example, whenever the specific node is created, the hook registered on that node gets called and the specific list can be updated with additional list entry or entries.

Version 19.10-12 Page 128

Page 129: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

If an application needs to perform additional validations, security check or any other manipulations with datastore in the same transaction, there are mechanisms implemented in the form of API functions called Transaction Hook, Start Transaction, and Complete Transaction.

If an application needs to perform additional actions and manipulations with datastore in the same transaction during <commit> operation, there are mechanisms implemented in the form of API functions called Startup Hook, Validate Complete, Apply Complete, Commit Complete or Rollback Complete callbacks. These callbacks are called Commit Completeness callbacks.

Manipulation with configuration data are only allowed for Set Hook and Post Set Hook callbacks, however. If Transaction Hook, Start/Complete Transaction, or Commit Completeness callbacks are trying to adjust configuration data via add_edit() API (an API function that allows to add edits on the fly within the same transaction, described later), theoperation will be skipped. However, this action will not generate an error, just a warning message in the log with log-level equals debug2.

NOTE:

In-Transaction callbacks are NOT part of the yangdump-sdk code generation. After the make_sil_dir_pro script is run, In-Transaction callbacks will NOT be auto-generated. All the In-Transaction callbacks are optional and merely intend to provide more efficient way to manipulate with the database and give an access to the database at the specific phase, transaction, and an edit.

Version 19.10-12 Page 129

Page 130: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.1 Callback Invocation Order

This section gives a quick overview for the callbacks invocation order.

Assume we register all the possible callbacks and the edit is complex as possible. The possible invocation order may look asfollows, processing on the <candidate> datastore (before the <commit>):

1. Transaction Start

2. Set Order Hook

3. Set Hook and then Set Order Hook for the added edit if any

4. SIL Callbacks (only during Validation Phase)

5. Post Set Hook and then Set Order Hook for the added edit if any

6. SIL Callbacks for added edits (only during Validation Phase)

7. Transaction Complete

The possible invocation order during the commit operation may look as follows, processing on the <running> datastore (after the <commit>):

1. Transaction Start

2. Set Order Hook

3. SIL Callbacks (Validate Phase)

4. Validate Complete

5. SIL Callbacks (Apply Phase)

6. Apply Complete

7. SIL Callbacks (Commit Phase)

8. Transaction Hook

9. Commit/Rollback Complete

10. Transaction Complete

The <commit> operation is not available if the default target is set to <running>. Thus, the possible invocation order during the edit operation may look as follows, processing on the running datastore only (the same invocation order will be during Load, Reload and Restart operations):

1. Transaction Start

2. Set Order Hook

3. Set Hook and then Set Order Hook for the added edit if any

4. SIL Callbacks (Validate Phase)

5. Post Set Hook and then Set Order Hook for the added edit if any

6. SIL Callbacks for added edits (Validate Phase)

7. SIL Callbacks (Apply Phase)

8. SIL Callbacks (Commit Phase)

Version 19.10-12 Page 130

Page 131: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

9. Transaction Hook

10. Transaction Complete

The possible invocation order during the validate operation may look as follows, processing on the <running> datastore only:

1. Transaction Start

2. Set Order Hook

3. SIL Callbacks (Validate Phase)

4. Transaction Complete

Set Hook, Post Set Hook and Transaction Hook callbacks will not be invoke during explicit <validate> command and in case of the following netconfd-pro parameters are set to TRUE:

--sil-validate-candidate (only relevant to Set Hook)

--sil-skip-load

Version 19.10-12 Page 131

Page 132: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.2 Set Hook Callback

A Set Hook is a function that is invoked within the transaction when an object is modified. When the netconfd-pro server has been configured to provide a candidate configuration, Set Hook code will be invoked when changes are done to the <candidate> configuration if the --target=candidate parameter is used. If --target=running then the Set Hook will be invoked at the start of the transaction on the running datastore. This callback will be invoked before a EDIT1 or EDIT2 callback for the same object. Refer to netconfd development manual for more information.

Set Hook can be invoked during the Load; However, it is not allowed to add new edits. So, callback are treated as Transaction Hook style hooks and can perform only validation tasks and cannot edit datastore. Any add_edit() during Load will be ignored, it is not an error just skip the call and go back with NO_ERR status.

The following function template definition is used for Set Hook callback functions:

/* Typedef of the agt_hook_cb callback */typedef status_t

(*agt_cb_hook_t)(ses_cb_t *scb, rpc_msg_t *msg,

agt_cfg_transaction_t *txcb, op_editop_t editop,

val_value_t *newval, val_value_t *curval);

Callback Template

• Type: User Callback

• Max Callbacks: 1 Set Hook callback per object

• File: agt_cb.h

• Template: agt_cb_hook_t

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ txcb == transaction control block in progress

▪ editop == edit operation enumeration for the node being edited

▪ newval == value holding the proposed changes to apply to the current config, depending on the editop value.

▪ curval == current values from the <running> or <candidate> configuration, if any. Could be NULL for create and other operations.

◦ Outputs: none

◦ Returns: status_t:Status of the callback function execution

• Register: agt_cb_hook_register

• Unregister: agt_cb_hook_unregister

Version 19.10-12 Page 132

Page 133: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.2.1 Set Hook Callback Initialization and Cleanup

A Set Hook database edit callback function is hooked into the server with the agt_cb_hook_register function, described below.

The agt_cb_hook_register function is used to declare the callback as a specific style callback. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

extern status_t agt_cb_hook_register (const xmlChar *defpath, agt_hook_fmt_t format, agt_hook_type_t type, agt_cb_hook_t cbfn);

agt_cb_hook_register

Parameter Description

defpath Absolute path expression string indicating which node the callback function is for.

format different hook formats dictates specific hook functionality

type different hook types dictates hook invocation point

cbfn address of callback function to use

NOTE:

Set Hook callbacks will not be invoke during explicit <validate> command and in case of the following netconfd-pro parameters are set to TRUE: --sil-validate-candidate or --sil-skip-load.

Initialization function with the registration of Set Hook callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

Version 19.10-12 Page 133

Page 134: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* Register an object specific Set Hook callback */ res = agt_cb_hook_register((const xmlChar *)”/if:trigger”,

AGT_HOOKFMT_NODE, AGT_HOOK_TYPE_SETHOOK, sethook_callback_edit);

...}

The format parameter is important when you want to specify how Set Hook callbacks will be invoked. There are two options available for this parameter:

• AGT_HOOKFMT_NODE: Set the type of the callback to this value if You want to make sure that the callback will be invoked only when you modify the node that registered the callback but not any of its children.

• AGT_HOOKFMT_SUBTREE: If the format is set to this value, the callback will be invoked if you edit children as well.

The type parameter is important when you want to set the type of callback. There are two options available for this parameter, either Set Hook or Transaction Hook callback:

• AGT_HOOK_TYPE_SETHOOK: Set the type of the callback to this value if You want to register Set Hook callback.

• AGT_HOOK_TYPE_TRANSACTION: Set the type of the callback to this value if You want to register Transaction Hook callback.

The following example code illustrates how hook-based callbacks can be cleaned up. The callbacks cleanup is getting done during module Cleanup Phase.

extern void agt_cb_hook_unregister (const xmlChar *defpath);

agt_cb_hook_unregister

Parameter Description

defpath Absolute path expression string indicating which node the callback function is for.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... agt_cb_hook_unregister((const xmlChar *)"/if:trigger");

...

Version 19.10-12 Page 134

Page 135: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

}

NOTE:

It is possible to register different callbacks for the same object, for instance, there can be Set Hook and Transaction Hook callbacks registered for the same object, as well as there can be EDIT or GET2 callbacks for the same object. However, in order to cleanup callbacks, unregister them, you need to run different cleanup functions. The EDIT and GET2 callbacks have their own unregister functions and hook-based callbacks have their own unregister function.

Version 19.10-12 Page 135

Page 136: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.2.2 Set Hook Callback and add_edit() API Function Examples

The following sections illustrates how to utilize the Set Hook callback in examples.

NOTE:

Manipulation with datastore are only allowed for Set Hook callbacks. If Transaction Hook or other In-Transaction callbacks call add_edit() the operation will be ignored. It will not return an error, just ignore add_edit calls.

Let us go through simple examples that will illustrate how to utilize the Set Hook callbacks for the specific purposes.

First we need a YANG module. Consider this simplified, but functional, example.

container interfaces { list interface { key "name";

leaf name { type string; } leaf speed { type enumeration { enum 10m; enum 100m; enum auto; } } leaf hook-node { type uint32; } container state { leaf admin-state { type boolean; } } }

leaf status { type string; } }

...

leaf trigger { type string; }

Version 19.10-12 Page 136

Page 137: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Add a new nodeAs specified in the previous section, Set Hook was registered for the “trigger” leaf element. Thus, whenever the node /if:trigger is edited, the callback function will be called and additional specific data can be updated or populated with desired values.

In this example, we will generate an extra “interface” list entry with key value equal to “vlan1” when a “trigger” node is getting edited with a specific value equal to “add-edit”.

The callback function may look as follows:

/******************************************************************** * FUNCTION sethook_callback_edit* * Callback function for server object handler * Used to provide a callback for a specific named object** Set Hook: * trigger: edit /if:trigger* add_edit: * add nodes: populate 1 list entry with name=vlan1** path: /if:interfaces/if:interface[if:name=vlan1]**********************************************************************/ static status_t sethook_callback_edit (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval) { log_debug("\nEnter SET Hook callback");

status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

const xmlChar *defpath = (const xmlChar *)"/if:interfaces";

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: /* add a new edit if the "/if:trigger" value is "add-edit" */ if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"add-edit")) {

/* find object template of the desired node */ obj_template_t *targobj = ncx_match_any_object_ex(EXAMPLE_MODNAME, (const xmlChar *)"interfaces", FALSE, NCX_MATCH_FIRST, FALSE, &res); if (!targobj) { return ERR_NCX_INVALID_VALUE; }

Version 19.10-12 Page 137

Page 138: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* create edit_value container value */ val_value_t *editval = val_new_value(); if (editval == NULL) { return ERR_INTERNAL_MEM; } val_init_from_template(editval, targobj);

/* malloce and construct list value, for more * examples refer to libhooks-test/src/hooks-test.c library

*/ uint32 key = 11; val_value_t *list_value = create_list_entry(VAL_OBJ(editval), key, &res); if (!list_value) { val_free_value(editval); return res; }

/* add a new list entry */ res = val_child_add(list_value, editval); if (res != NO_ERR) { val_free_value(list_value); } else { /* add a new edit, MERGE on defpath with 1 new list entry */ res = agt_val_add_edit(scb, msg, txcb, defpath, editval, OP_EDITOP_MERGE); }

/* clean up the editval */ val_free_value(editval); } break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* sethook_callback_edit */

Version 19.10-12 Page 138

Page 139: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

As a result, whenever some north bound agent edit the /if:trigger with a specific value, the callback is invoked and additionally creates a new interface /if:interfaces/if:interface[if:name=value]

The function that is responsible for the list entry creation may look as follows:

/********************************************************************* FUNCTION create_list_entry* * Make a list entry based on the key** INPUTS:* parentobj == parent object template to use* keyname == value of the key* res = return status** RETURNS:* val_value_t of listval entry if no error* else NULL**********************************************************************/static val_value_t * create_list_entry(obj_template_t *parentobj, const xmlChar *keyname, status_t *res){ /* get the obj template for the list obj */ obj_template_t *list_obj = obj_find_child(parentobj, EXAMPLE_MODNAME, (const xmlChar *)"interface"); if (!list_obj) { *res = ERR_NCX_INVALID_VALUE; return NULL; }

/* add all the /container/list nodes */ val_value_t *list_value = val_new_value(); if (!list_value) { *res = ERR_NCX_INVALID_VALUE; return NULL; } val_init_from_template(list_value, list_obj);

/* make key leaf entry */ val_value_t *child = agt_make_leaf(list_obj, (const xmlChar *)"name", keyname, res); if (!child) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; } *res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(list_value); return NULL; }

Version 19.10-12 Page 139

Page 140: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* make some extra leaf entries */ child = agt_make_uint_leaf(list_obj, (const xmlChar *)"hook-node", (uint32)1000, res); if (!child) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; } *res = val_child_add(child, list_value); if (*res != NO_ERR) { val_free_value(child); 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) { log_error("\nError: could not generate index chain (%s)", get_error_string(*res)); val_free_value(list_value); return NULL; }

return list_value;

} /* create_list_entry */

NOTE:

When you are constructing a list node make sure that a key node is getting created first, and then all other children are getting added. Also, make sure that you use val_gen_index_chain API function after you construct the list, so it will be normalized and all required fields will be set accordingly.

To ensure that the data added by add_edit was successfully generated an application can retrieve running configuration anddevice state information. The server should reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interfaces xmlns="http://yumaworks.com/ns/interfaces"> </interface> <name>vlan1</name>

<observed-speed>1000</observed-speed>

</interface> </interfaces>

<trigger>add-edit</trigger> </rpc-reply>

Version 19.10-12 Page 140

Page 141: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Delete nodeAs specified earlier, Set Hook was registered for the “trigger” leaf element. Thus, whenever the node /if:trigger is edited, the callback function will be called and additional specific data can be updated or populated with desired values.

In this example, we will delete just added /if:interface container with all its children when a “trigger” node is getting deleted.

The callback function may look as follows:

/******************************************************************** * FUNCTION sethook_callback_edit* * Callback function for server object handler * Used to provide a callback for a specific named object** Set Hook: * trigger: delete /trigger* add_edit: * delete nodes: delete the whole container** path: /if:interfaces**********************************************************************/ static status_t sethook_callback_edit (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval) { log_debug("\nEnter SET Hook callback");

status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

const xmlChar *defpath = (const xmlChar *)"/if:interfaces";

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: break; case OP_EDITOP_DELETE: /* delete the interfaces container if the curval of 'trigger' node is * "delete-all" */

if (curval && !xml_strcmp(VAL_STR(curval), (const xmlChar *)"delete-all")) { res = agt_val_add_edit(scb, msg, txcb, defpath, NULL, // editval editop);

Version 19.10-12 Page 141

Page 142: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

} break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* sethook_callback_edit */

As a result, the server will deletes the whole /if:interfaces container if “trigger” value is set to 'delete-all' and some north bound agent attempts to DELETE /trigger node.

To ensure that the data deleted by add_edit was successfully deleted an application can retrieve running configuration and device state information. The server should reply with:

<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">

<data></data> </rpc-reply>

Version 19.10-12 Page 142

Page 143: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Update nodeConsider the same data model as for the previous examples; however, now we will register callback for the top level /if:interfaces container element. In this example, we will populate an extra leafs when the container node is created.

Register a Set Hook to the /if:interfaces container.

/* Register an object specific Set Hook callback */ res = agt_cb_hook_register((const xmlChar*)"/if:interface", AGT_HOOKFMT_NODE, AGT_HOOK_TYPE_SETHOOK, sethook_callback_edit);

Now, when user wants to create the container, the callback function will be called and container can be updated with desiredadditional values.

NOTE:

Callback format should be AGT_HOOKFMT_NODE in order to invoke this callback only for a new container edit. If the format is AGT_HOOKFMT_SUBTREE, the callback will be invoked if you edit children as well. In this case newval will not represent container value and cannot not be used to construct a new updated edit value.

The callback function may look as follows:

/******************************************************************** * FUNCTION sethook_callback_edit* * Callback function for server object handler * Used to provide a callback for a specific named object * * Set Hook: * trigger: create /interfaces* create container and populate extra nodes * * add_edit effect: populate extra nodes within the container * when /interfaces is created * *********************************************************************/ static status_t sethook_callback_edit (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval) { log_debug("\nEnter SET Hook callback");

status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

Version 19.10-12 Page 143

Page 144: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* defpath specified target root */ const xmlChar *defpath = (const xmlChar *)"/if:interfaces"; switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE:

break; case OP_EDITOP_CREATE: /* populate a new container with several leafs */ if (newval) {

/* use newval value to write a new edits */ val_value_t *editval = val_clone_config_data(newval, &res); if (editval == NULL) { return ERR_INTERNAL_MEM; }

/* malloced and construct some leaf values */ val_value_t *child = agt_make_leaf(VAL_OBJ(editval), (const xmlChar *)"status", (const xmlChar *)"extra-leaf", &res); if (!child) { val_free_value(editval); return ERR_NCX_INVALID_VALUE; } res = val_child_add(child, editval); if (res != NO_ERR) { val_free_value(child); } else { /* add a new edit on defpath and populate new entries */ res = agt_val_add_edit(scb, msg, txcb, defpath, editval, OP_EDITOP_MERGE); }

/* clean up the editval */ val_free_value(editval); } break; case OP_EDITOP_DELETE:

break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE,

Version 19.10-12 Page 144

Page 145: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* sethook_callback_edit */

As a result, whenever some north bound agent creates an /interfaces container the callback is invoked and additionally creates a new leafs within this container.

Version 19.10-12 Page 145

Page 146: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Modify NODE Value 1

Consider the same data model as for the previous examples; however, now we will register callback for the top level /if:trigger leaf. In this example, we will modify its value on the fly when the leaf node is created.

/* Register an object specific Set Hook callback */ res = agt_cb_hook_register((const xmlChar*)"/if:trigger", AGT_HOOKFMT_NODE, AGT_HOOK_TYPE_SETHOOK, sethook_callback_edit);

The callback function may look as follows:

/********************************************************************* FUNCTION sethook_callback_edit** Callback function for server object handler* Used to provide a callback for a specific named object** Set Hook:* trigger: edit /if:trigger* Effect: change 'trigger' node value to a custom value***********************************************************************/static status_t sethook_callback_edit (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval){ log_debug("\nEnter SET Hook callback");

status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

const xmlChar *defpath = (const xmlChar *)"/if:trigger";

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: /* modify "/if:trigger" value on the fly */ if (newval && !xml_strcmp(VAL_NAME(newval), (const xmlChar *)"trigger")) {

/* This is just an example string value. * Generate you own custom value for a new node here. */

Version 19.10-12 Page 146

Page 147: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

const xmlChar *newval = (const xmlChar *)"delete-all";

log_info("\n changing %s to %s \n", VAL_STR(newval), newval);

/* change the value */ m__free(VAL_STR(newval)); VAL_STR(newval) = xml_strdup(newval);

/* in the case we do NOT have to call add_edit() */ (void)defpath; (void)txcb; // res = agt_val_add_edit(scb, // msg, // txcb, // defpath, // editval, // OP_EDITOP_MERGE); } break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* sethook_callback_edit */

NOTE:

If your desired node is a leaf within a container or list you may want to register the Set Hook callback on the container or list and then find your desired value you want to modify or create and then perform desired actions. Otherwise, if you register Set Hook callback on the leaf node within container the server will not invoke Set Hook callbacks when you createthe container.

Also, another solution is to make sure that the container or list already pre-exist and only after that you may edit desired leaf node in the container and apply desired actions.

Version 19.10-12 Page 147

Page 148: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Modify NODE Value 2

Consider the same data model as for the previous examples; however, now we will register callback for the /if:interfaces/if:interface list node. In this example, we will modify /if:interfaces/if:interface/if:state container node children values. The trigger for the edit will be creation of a new interface with specific name value.

/* Register an object specific Set Hook callback */ res = agt_cb_hook_register((const xmlChar*)"/if:interfaces/if:interface", AGT_HOOKFMT_NODE, AGT_HOOK_TYPE_SETHOOK, sethook_callback_edit);

Assume we have the running datastore configured as follows:

data { ietf-interfaces:interfaces { interface vlan2 { name vlan2 type ianaift:l2vlan } interface vlan1 { name vlan1 type ianaift:l2vlan state { admin-state false } } } }}

And now we want to modify "state" container value when a new interface with specific value is created. In our example, a new interface value will be "LAG" that will trigger a "state" container change.

The callback function may look as follows:

/********************************************************************* FUNCTION sethook_callback_edit** Callback function for server object handler* Used to provide a callback for a specific named object** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* txcb == transaction control block in progress* editop == edit operation enumeration for the node being edited* newval == container object holding the proposed changes to* apply to the current config, depending on

Version 19.10-12 Page 148

Page 149: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* the editop value. Will not be NULL.* curval == current container values from the <running>* or <candidate> configuration, if any. Could be NULL* for create and other operations.** RETURNS:* status*********************************************************************/static status_t sethook_callback_edit (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval){ status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval; val_value_t *child_val = NULL;

/* defpath specified target */ const xmlChar *defpath = (const xmlChar *)"/if:interfaces/if:interface[name='vlan1']/if:state";

if (newval) { child_val = val_find_child(newval, (const xmlChar *)"ietf-interfaces", (const xmlChar *)"name"); if (child_val) { log_debug("\n>>>>>>>>>> " " callback for %s editop, name=%s", op_editop_name(editop), VAL_STR(child_val)); } }

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: if (newval && !val_is_default(newval) && child_val && !xml_strcmp(VAL_STR(child_val), (const xmlChar *)"LAG")) {

val_value_t *testval = agt_val_get_data(txcb->cfg_id,(const xmlChar *)"/if:interfaces/if:interface[name='vlan1']/if:state", &res);

val_value_t *editval = NULL; if (testval) { /* clone just found value in order to write a new edits */ editval = val_clone_config_data(testval, &res); if (!editval) { return ERR_NCX_INVALID_VALUE; } else { /* Only when edit target is container or list. * Need to clean any found children in order to * make a new edit and a new value. * Otherwise if the target children leaf exist in this * container the val_add_child() will fail. */

Version 19.10-12 Page 149

Page 150: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_delete_children(editval); } } else { return ERR_NCX_INVALID_VALUE; }

/* add any other children to target container, can add any amount * of children here. * In this example we add one leaf "admin-state" with value "true" */ obj_template_t *chobj = obj_find_child(testval->obj, (const xmlChar *)"ietf-interfaces", (const xmlChar *)"admin-state"); if (chobj) { val_value_t *child = val_make_simval_obj(chobj, (const xmlChar *)"true", &res); if (child) { val_add_child(child, editval); } else { val_free_value(editval); return ERR_NCX_INVALID_VALUE; } } else { val_free_value(editval); return ERR_NCX_INVALID_VALUE; }

/* add a new edit on defpath and populate new entry */ if (res == NO_ERR) {

/* defpath specified target */// const xmlChar *defpath =// (const xmlChar *)"/if:interfaces/if:interface[name='vlan1']/if:state";

res = agt_val_add_edit(scb, msg, txcb, defpath, editval, OP_EDITOP_MERGE); } /* clean up the editval */ val_free_value(editval); } break; case OP_EDITOP_DELETE:

break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval);

Version 19.10-12 Page 150

Page 151: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

}

return res;

} /* sethook_callback_edit */

As a result, whenever some north bound agent creates a new interface with name "LAG", the callback will modify the interface with name "vlan1" and update the "admin-state" value. The final running datastore result may look as follows:

data { ietf-interfaces:interfaces { interface vlan2 { name vlan2 type ianaift:l2vlan } interface vlan1 { name vlan1 type ianaift:l2vlan state { admin-state true } } interface LAG { name LAG type ianaift:ieee8023adLag } } }}

Version 19.10-12 Page 151

Page 152: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.2.3 Set Hook Callback and add_edit_ex() API Function Examples

This section will demonstrate and exemplify how to insert or move a specific list or leaf-list entry with help of add_edit_ex() API.

The add_edit_ex() API is only allowed to be used within the Set Hook callbacks as described in the previous sections.

NOTE:

The server does not support the "insert" and "move" operation on the nodes that are being modified at the same transaction at the same time. That's if the server already has an undo record (an edit on specific node), then the "insert" or "move" add_edit_ex() API on the same specific node will return an error. The server will only insert a new nodes and move only existent nodes. It will not move a new nodes or a nodes that are being already modified.

Let us go through simple examples that will illustrate how to utilize the Set Hook callbacks for the specific purpose, such as insert or move an entry. First we need a YANG module. Consider this simplified, but functional, example module:

module example { namespace "http://netconfcentral.org/ns/example"; prefix "ex";

revision 2019-01-01 { description "Initial revision."; }

leaf insert-list-check { type string; }

leaf insert-leaf-list-check { type string; }

leaf move-list-check { type string; }

leaf move-leaf-list-check { type string; }

list hook-list-test { key name; ordered-by user;

leaf name { type string; } leaf a2 { type string; } leaf b2 { type uint32;

Version 19.10-12 Page 152

Page 153: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

default 5; } }

leaf-list hook-leaf-list-test { ordered-by user; type string; }

}

Version 19.10-12 Page 153

Page 154: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Insert new list nodes

Assume we registered Set Hook callback for the “insert-list-check” leaf element. Thus, whenever the node /ex:insert-list-check is edited, the callback function will be called and additional specific entry can be inserted or moved within the datastore.

In this example, we will insert a new “hook-list-test” list entries when a “insert-list-check” node is modified with specific value equal to. For example, assume we will send the edits with following "insert-list-check" values (trigger, trigger2, trigger3, trigger4). As a result the Set Hook callback function may look as follows:

#define HOOKS_TEST_MOD (const xmlChar *)"example"#define HOOKS_TEST_REV (const xmlChar *)"2019-01-01"

/********************************************************************* FUNCTION create_list_entry** Make a list entry based on the key** INPUTS:* res = return status** RETURNS:* val_value_t of listval entry if no error* else NULL**********************************************************************/static val_value_t * create_list_entry (obj_template_t *list_obj, const xmlChar *keyname, const xmlChar *keystr, status_t *res){ /* add all the /container/list nodes */ val_value_t *list_value = val_new_value(); if (!list_value) { *res = ERR_NCX_INVALID_VALUE; return NULL; } val_init_from_template(list_value, list_obj);

/* make key leaf entry */ val_value_t *child = agt_make_leaf(list_obj, keyname, keystr, res); if (!child) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; } val_add_child(child, list_value);

/* generate the internal index Q chain */ *res = val_gen_index_chain(list_obj, list_value); if (*res != NO_ERR) { log_error("\nError: could not generate index chain (%s)", get_error_string(*res));

Version 19.10-12 Page 154

Page 155: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_free_value(list_value); return NULL; }

return list_value;

} /* create_list_entry */

/********************************************************************* FUNCTION hooks_sethook_edit_insert** Callback function for server object handler* Used to provide a callback for a specific named object** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* txcb == transaction control block in progress* editop == edit operation enumeration for the node being edited* newval == container object holding the proposed changes to* apply to the current config, depending on* the editop value. Will not be NULL.* curval == current container values from the <running>* or <candidate> configuration, if any. Could be NULL* for create and other operations.** RETURNS:* status*********************************************************************/static status_t hooks_sethook_edit_insert (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval){ status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

/* look for a top-node data object */ obj_template_t *targobj = ncx_match_any_object_ex(HOOKS_TEST_MOD, (const xmlChar *)"hook-list-test", FALSE, NCX_MATCH_FIRST, FALSE, &res); if (!targobj) { return ERR_NCX_NOT_FOUND; }

val_value_t *editval = NULL; const xmlChar *defpath = NULL; const xmlChar *edit_operation = NULL; const xmlChar *insert_point = NULL; const xmlChar *insert_where = NULL;

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE:

Version 19.10-12 Page 155

Page 156: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: /* INSERT KEY2 AFTER KEY1 */ if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger")) {

editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key2", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key2']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"after";

/* assume we already have key1 in the datastore */ insert_point = (const xmlChar *)"/ex:hook-list-test[name='key1']";

/* INSERT KEY3 BEFORE KEY1 */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger2")) {

editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key3", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key3']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-list-test[name='key1']";

/* INSERT KEY4 LAST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger3")) {

editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key4", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key4']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"last"; insert_point = NULL;

/* INSERT KEY5 FIRST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger4")) {

Version 19.10-12 Page 156

Page 157: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key5", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key5']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"first"; insert_point = NULL;

/* Negative test, missing insert point */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail")) {

editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"NEW", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='NEW']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-list-test[name='MISSING']";

/* Negative test, where is missing */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail2")) {

editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"NEW", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='NEW']"; edit_operation = (const xmlChar *)"insert"; insert_where = NULL; insert_point = (const xmlChar *)"/ex:hook-list-test[name='key2']";

} else { /* nothing to add or modify. Specific criteria not met */ break; }

/* add a new edit on defpath and populate new entry */ if (res == NO_ERR) {

Version 19.10-12 Page 157

Page 158: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

res = agt_val_add_edit_ex(scb, msg, txcb, defpath, editval, edit_operation, insert_where, insert_point); }

if (editval) { /* clean up the editval */ val_free_value(editval); }

/* Final Result should look as follows: * * example:hook-list-test key5 { inserted 'first' by Set-Hook * name key5 * } * example:hook-list-test key3 { inserted 'before' by Set-Hook * name key3 * } * example:hook-list-test key1 { created by edit-config * name key1 * } * example:hook-list-test key2 { inserted 'after' by Set-Hook * name key2 * } * example:hook-list-test key4 { inserted 'last' by Set-Hook * name key4 * } * */

break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); } return res;

} /* hooks_sethook_edit_insert */

/********************************************************************* FUNCTION init_example_test** Initialize the example module callbacks*

Version 19.10-12 Page 158

Page 159: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

*********************************************************************/static status_t init_example_test (void){ status_t res = NO_ERR;

res = agt_cb_hook_register((const xmlChar *)"/ex:insert-list-check", AGT_HOOKFMT_NODE, AGT_HOOK_TYPE_SETHOOK, hooks_sethook_edit_insert); if (res != NO_ERR) { return res; }

return NO_ERR;

} /* init_example_test */

/********************************************************************* FUNCTION cleanup_example_test** Cleanup the example module callbacks**********************************************************************/static void cleanup_example_test (void){ agt_cb_hook_unregister((const xmlChar *)"/ex:insert-list-check");

} /* cleanup_example_test */

Now let us go through the example above.

1) Callback register/unregister

As illustrated in the example above we register and unregister Set Hook callback the same way as described in the previoussections. Refer to previous section for more details on how to register and unregister Set Hook callbacks.

2) The most interesting part of the example is the callback itself. In the callback we triggering the add_edit_ex() API based on the "insert-list-check" leaf value. We insert a specific and new list entry based on the "insert-list-check" value.

...

/* INSERT KEY2 AFTER KEY1 if "newval" has value of 'trigger' */ if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger")) {

...

In order to create a new list entry and insert it we need to create a val_value_t structure first that represents the "hook-list-test" list node as illustrated in the example:

/********************************************************************* FUNCTION create_list_entry

Version 19.10-12 Page 159

Page 160: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

** Make a list entry based on the key** INPUTS:* res = return status** RETURNS:* val_value_t of listval entry if no error* else NULL**********************************************************************/static val_value_t * create_list_entry (obj_template_t *list_obj, const xmlChar *keyname, const xmlChar *keystr, status_t *res){ /* add all the /container/list nodes */ val_value_t *list_value = val_new_value(); if (!list_value) { *res = ERR_NCX_INVALID_VALUE; return NULL; } val_init_from_template(list_value, list_obj);

/* make key leaf entry */ val_value_t *child = agt_make_leaf(list_obj, keyname, keystr, res); if (!child) { val_free_value(list_value); *res = ERR_NCX_INVALID_VALUE; return NULL; } val_add_child(child, list_value);

/* generate the internal index Q chain */ *res = val_gen_index_chain(list_obj, list_value); if (*res != NO_ERR) { log_error("\nError: could not generate index chain (%s)", get_error_string(*res)); val_free_value(list_value); return NULL; }

return list_value;

} /* create_list_entry */

3) After we constructed the list node val_value_t tree we are ready to insert this node into the datastore with help of add_edit_ex() API as illustrated in the example:

...

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key2']";

Version 19.10-12 Page 160

Page 161: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"after";

/* assume we already have key1 in the datastore */ insert_point = (const xmlChar *)"/ex:hook-list-test[name='key1']"; }

/* add a new edit on defpath and populate new entry */ if (res == NO_ERR) { res = agt_val_add_edit_ex(scb, msg, txcb, defpath, editval, edit_operation, insert_where, insert_point);

.....

4) After the callback is called multiple times with different values for "insert-list-check". Assume we send multiple <edit-config> requests with different "insert-list-check" values the data store may look as follows:

/* Final Result should look as follows: * * example:hook-list-test key5 { inserted 'first' by Set-Hook * name key5 * } * example:hook-list-test key3 { inserted 'before' by Set-Hook * name key3 * } * example:hook-list-test key1 { created by edit-config * name key1 * } * example:hook-list-test key2 { inserted 'after' by Set-Hook * name key2 * } * example:hook-list-test key4 { inserted 'last' by Set-Hook * name key4 * } * */

Version 19.10-12 Page 161

Page 162: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Move list nodes

In this example we will do the same steps but for the move operation and for list nodes. That's, we will try to move existent in the datastore list entries based on different "move-list-check" leaf node values.

The example callback may look as follow, assume we are following the same steps for register and unregister as in the previous example:

#define HOOKS_TEST_MOD (const xmlChar *)"example"#define HOOKS_TEST_REV (const xmlChar *)"2019-01-01"

/********************************************************************* FUNCTION hooks_sethook_edit_move** Callback function for server object handler* Used to provide a callback for a specific named object*** The current datastore entries should look as follows:** example:hook-list-test key5 { // will be moved last* name key5* }* example:hook-list-test key3 { // will be moved before 'key4'* name key3* }* example:hook-list-test key1 { // will be moved first* name key1* }* example:hook-list-test key2 { // will be moved after 'key3'* name key2* }* example:hook-list-test key4 {* name key4* }*** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* txcb == transaction control block in progress* editop == edit operation enumeration for the node being edited* newval == container object holding the proposed changes to* apply to the current config, depending on* the editop value. Will not be NULL.* curval == current container values from the <running>* or <candidate> configuration, if any. Could be NULL* for create and other operations.** RETURNS:* status*********************************************************************/static status_t hooks_sethook_edit_move (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval,

Version 19.10-12 Page 162

Page 163: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

val_value_t *curval){ status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

/* look for a top-node data object */ obj_template_t *targobj = ncx_match_any_object_ex(HOOKS_TEST_MOD, (const xmlChar *)"hook-list-test", FALSE, NCX_MATCH_FIRST, FALSE, &res); if (!targobj) { return ERR_NCX_NOT_FOUND; }

val_value_t *editval = NULL; const xmlChar *defpath = NULL; const xmlChar *edit_operation = NULL; const xmlChar *insert_point = NULL; const xmlChar *insert_where = NULL;

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE:

/* MOVE KEY2 AFTER KEY3 */ if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key2", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key2']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"after"; insert_point = (const xmlChar *)"/ex:hook-list-test[name='key3']";

/* MOVE KEY3 BEFORE KEY4 */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger2")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move

Version 19.10-12 Page 163

Page 164: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

*/ editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key3", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key3']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-list-test[name='key4']";

/* MOVE KEY5 LAST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger3")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key5", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key5']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"last"; insert_point = NULL;

/* MOVE KEY1 FIRST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger4")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key1", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key1']"; edit_operation = (const xmlChar *)"move";

Version 19.10-12 Page 164

Page 165: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

insert_where = (const xmlChar *)"first"; insert_point = NULL;

/* Negative test, missing move point */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key1", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key1']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-list-test[name='MISSING']";

/* Negative test, missing target */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail2")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"MISSING", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='MISSING']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"first";

/* Negative test, where is missing */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail3")) {

/* make list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval =

Version 19.10-12 Page 165

Page 166: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

create_list_entry(targobj, (const xmlChar *)"name", (const xmlChar *)"key1", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-list-test[name='key1']"; edit_operation = (const xmlChar *)"move"; insert_where = NULL; insert_point = (const xmlChar *)"/ex:hook-list-test[name='key2']";

} else { /* nothing to add or modify. Specific criteria not met */ break; }

/* add a new edit on defpath and populate new entry */ if (res == NO_ERR) { res = agt_val_add_edit_ex(scb, msg, txcb, defpath, editval, edit_operation, insert_where, insert_point); }

if (editval) { /* clean up the editval */ val_free_value(editval); }

/* Final Result should look as follows: * * example:hook-list-test key1 { * name key1 * } * example:hook-list-test key2 { * name key2 * } * example:hook-list-test key3 { * name key3 * } * example:hook-list-test key4 { * name key4 * } * example:hook-list-test key5 { * name key5 * } */

break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) {

Version 19.10-12 Page 166

Page 167: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); } return res;

} /* hooks_sethook_edit_move */

After the callback is called multiple times with different values for "move-list-check". Assume we send multiple <edit-config> requests with different "move-list-check" values the data store may look as follows:

/* Final Result should look as follows: * * example:hook-list-test key1 { * name key1 * } * example:hook-list-test key2 { * name key2 * } * example:hook-list-test key3 { * name key3 * } * example:hook-list-test key4 { * name key4 * } * example:hook-list-test key5 { * name key5 * } */

Version 19.10-12 Page 167

Page 168: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Insert new leaf-list nodes

In this example we will do the same steps but for leaf-list nodes. That's we will try to insert leaf-list entries instead of list entries based on different "insert-leaf-list-check" leaf node values.

The example callback may look as follow, assume we are following the same steps for register and unregister as in the previous example:

#define HOOKS_TEST_MOD (const xmlChar *)"example"#define HOOKS_TEST_REV (const xmlChar *)"2019-01-01"

/********************************************************************* FUNCTION hooks_sethook_edit_insert2** Callback function for server object handler* Used to provide a callback for a specific named object** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* txcb == transaction control block in progress* editop == edit operation enumeration for the node being edited* newval == container object holding the proposed changes to* apply to the current config, depending on* the editop value. Will not be NULL.* curval == current container values from the <running>* or <candidate> configuration, if any. Could be NULL* for create and other operations.** RETURNS:* status*********************************************************************/static status_t hooks_sethook_edit_insert2 (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval){ status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

/* look for a top-node data object */ obj_template_t *targobj = ncx_match_any_object_ex(HOOKS_TEST_MOD, (const xmlChar *)"hook-leaf-list-test", FALSE, NCX_MATCH_FIRST, FALSE, &res); if (!targobj) { return ERR_NCX_NOT_FOUND; }

val_value_t *editval = NULL; const xmlChar *defpath = NULL; const xmlChar *edit_operation = NULL;

Version 19.10-12 Page 168

Page 169: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

const xmlChar *insert_point = NULL; const xmlChar *insert_where = NULL;

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE: /* INSERT Leaf-list .=ll2 AFTER .=ll1 */ if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll2", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll2']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"after"; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll1']";

/* INSERT Leaf-list .=ll3 BEFORE .=ll1 */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger2")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll3", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll3']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll1']";

/* INSERT Leaf-list .=ll4 LAST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger3")) {

Version 19.10-12 Page 169

Page 170: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll4", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll4']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"last"; insert_point = NULL;

/* INSERT Leaf-list .=ll5 FIRST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger4")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll5", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll5']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"first"; insert_point = NULL;

/* Negative test, missing insert point */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"NEW", &res);

Version 19.10-12 Page 170

Page 171: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='NEW']"; edit_operation = (const xmlChar *)"insert"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='MISSING']";

/* Negative test, where is missing */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail2")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"NEW", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='NEW']"; edit_operation = (const xmlChar *)"insert"; insert_where = NULL; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll2']"; } else { /* nothing to add or modify. Specific criteria not met */ break; }

/* add a new edit on defpath and populate new entry */ if (res == NO_ERR) { res = agt_val_add_edit_ex(scb, msg, txcb, defpath, editval, edit_operation, insert_where, insert_point); }

if (editval) { /* clean up the editval */ val_free_value(editval); }

/* Final Result should look as follows: * * example:hook-leaf-list-test { * ll5 inserted 'first' by Set-Hook * ll3 inserted 'before' by Set-Hook * ll1 created by edit-config * ll2 inserted 'after' by Set-Hook

Version 19.10-12 Page 171

Page 172: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* ll4 inserted 'last' by Set-Hook * } * */

break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); } return res;

} /* hooks_sethook_edit_insert2 */

After the callback is called multiple times with different values for "insert-leaf-list-check". Assume we send multiple <edit-config> requests with different "insert-leaf-list-check" values the data store may look as follows:

/* Final Result should look as follows: * * example:hook-leaf-list-test { * ll5 inserted 'first' by Set-Hook * ll3 inserted 'before' by Set-Hook * ll1 created by edit-config * ll2 inserted 'after' by Set-Hook * ll4 inserted 'last' by Set-Hook * } * */

Version 19.10-12 Page 172

Page 173: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Move leaf-list nodes

In this example we will do the same steps but for the move operation and for leaf-list nodes. That's, we will try to move existent in the datastore leaf-list entries based on different "move-leaf-list-check" leaf node values.

The example callback may look as follow, assume we are following the same steps for register and unregister as in the previous example:

#define HOOKS_TEST_MOD (const xmlChar *)"example"#define HOOKS_TEST_REV (const xmlChar *)"2019-01-01"

/********************************************************************* FUNCTION hooks_sethook_edit_move2** Callback function for server object handler* Used to provide a callback for a specific named object** The current datastore entries should look as follows:** example:hook-leaf-list-test {* ll5 // will be moved last* ll3 // will be moved before ll4* ll1 // will be moved first* ll2 // will be moved after ll3* ll4* }** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* txcb == transaction control block in progress* editop == edit operation enumeration for the node being edited* newval == container object holding the proposed changes to* apply to the current config, depending on* the editop value. Will not be NULL.* curval == current container values from the <running>* or <candidate> configuration, if any. Could be NULL* for create and other operations.** RETURNS:* status*********************************************************************/static status_t hooks_sethook_edit_move2 (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval){ status_t res = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

print_callback_info(errorval, AGT_CB_VALIDATE, editop, (const xmlChar *)"SETHOOK-MOVE");

Version 19.10-12 Page 173

Page 174: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* look for a top-node data object */ obj_template_t *targobj = ncx_match_any_object_ex(HOOKS_TEST_MOD, (const xmlChar *)"hook-leaf-list-test", FALSE, NCX_MATCH_FIRST, FALSE, &res); if (!targobj) { return ERR_NCX_NOT_FOUND; }

val_value_t *editval = NULL; const xmlChar *defpath = NULL; const xmlChar *edit_operation = NULL; const xmlChar *insert_point = NULL; const xmlChar *insert_where = NULL;

switch (editop) { case OP_EDITOP_LOAD: break; case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE:

/* MOVE leaf-list .='key2' AFTER leaf-list .='key3' */ if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll2", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll2']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"after"; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll3']";

/* MOVE leaf-list .='key3' BEFORE leaf-list .='key4' */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger2")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj,

Version 19.10-12 Page 174

Page 175: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

(const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll3", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll3']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll4']";

/* MOVE leaf-list .='key5' LAST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger3")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll5", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll5']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"last"; insert_point = NULL;

/* MOVE leaf-list .='key1' FIRST */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger4")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll1", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll1']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"first"; insert_point = NULL;

Version 19.10-12 Page 175

Page 176: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* Negative test, missing move point */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll1", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll1']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"before"; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='MISSING']";

/* Negative test, missing target */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail2")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"MISSING", &res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='MISSING']"; edit_operation = (const xmlChar *)"move"; insert_where = (const xmlChar *)"first";

/* Negative test, where is missing */ } else if (newval && !xml_strcmp(VAL_STR(newval), (const xmlChar *)"trigger-fail3")) {

/* make leaf-list entry. * * The editval is optinal for MOVE operation, * It will be ignored by the add_edit API. The server will * use 'defpath' value as a current target value to move */ editval = agt_make_leaf(targobj, (const xmlChar *)"hook-leaf-list-test", (const xmlChar *)"ll1",

Version 19.10-12 Page 176

Page 177: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

&res); if (!editval) { return res; }

/* defpath specified target */ defpath = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll1']"; edit_operation = (const xmlChar *)"move"; insert_where = NULL; insert_point = (const xmlChar *)"/ex:hook-leaf-list-test[.='ll2']"; } else { /* nothing to add or modify. Specific criteria not met */ break; }

/* add a new edit on defpath and populate new entry */ if (res == NO_ERR) { res = agt_val_add_edit_ex(scb, msg, txcb, defpath, editval, edit_operation, insert_where, insert_point); }

if (editval) { /* clean up the editval */ val_free_value(editval); }

/* Final Result should look as follows: * * example:hook-leaf-list-test { * "ll1", * "ll2", * "ll3", * "ll4", * "ll5" * } * */

break; case OP_EDITOP_DELETE: break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); } return res;

Version 19.10-12 Page 177

Page 178: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

} /* hooks_sethook_edit_move2 */

After the callback is called multiple times with different values for "move-leaf-list-check". Assume we send multiple <edit-config> requests with different "move-leaf-list-check" values the data store may look as follows:

/* Final Result should look as follows: * * example:hook-leaf-list-test { * "ll1", * "ll2", * "ll3", * "ll4", * "ll5" * } * */

Version 19.10-12 Page 178

Page 179: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.3 Post Set Hook Callback

A Post Set Hook callback - is a postponed Set Hook callback analogous function that is invoked within the transaction when an object is modified but AFTER EDIT callback is done for the same object. When the netconfd-pro server has been configured to provide a candidate configuration, Post Set Hook code will be invoked when changes are done to the <candidate> configuration if the --target=candidate parameter is used. If –target=running then the Post Set Hook will beinvoked at the start of the transaction on the <running> datastore. This callback will be invoked AFTER a EDIT1 or EDIT2 callback for the same object.

NOTE:

This callback will not be invoked in case the --sil-root-check-first is set to TRUE when the server is run with --target=running. The server will ignore the callback and just skip its invocation.

Post Set Hook can be invoked during the Load; However, it is not allowed to add new edits. So, callbacks are treated as Transaction Hook style callbacks and can perform only validation tasks and cannot edit datastore. Any add_edit() API during Load will be ignored, it is not an error just skip the call and go back with NO_ERR status.

The following function template definition is used for Post Set Hook callback functions:

/* Typedef of the agt_hook_cb callback */typedef status_t

(*agt_cb_hook_t)(ses_cb_t *scb, rpc_msg_t *msg,

agt_cfg_transaction_t *txcb, op_editop_t editop,

val_value_t *newval, val_value_t *curval);

Callback Template

• Type: User Callback

• Max Callbacks: 1 Post Set Hook callback per object• File: agt_cb.h • Template: agt_cb_hook_t

• Inputs:• scb == session control block making the request• msg == incoming rpc_msg_t in progress • txcb == transaction control block in progress • editop == edit operation enumeration for the node being edited • newval == value holding the proposed changes to apply to the current config, depending on the

editop value. • curval == current values from the <running> or <candidate>configuration, if any. Could be

NULL for create and other operations.• Outputs: none• Returns: status_t: Status of the callback function execution

Version 19.10-12 Page 179

Page 180: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

• Register: agt_cb_post_hook_register • Unregister: agt_cb_post_hook_unregister

6.3.1 Post Set Hook Callback Initialization and Cleanup

A Post Set Hook callback function is hooked into the server with the agt_cb_post_sethook_register function, described below. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

extern status_t agt_cb_post_sethook_register (const xmlChar *defpath, agt_cb_hook_t cbfn);

agt_cb_post_sethook_register

Parameter Description

defpath Absolute path expression string indicating which node the callback function is for.

cbfn address of callback function to use

NOTE:

Post Set Hook callbacks will not be invoke during explicit <validate> command and in case of the following netconfd-pro parameters are set to TRUE: --sil-validate-candidate or --sil-skip-load.

Initialization function with the registration of Post Set Hook callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ... /* Register an object specific Post Set Hook callback */ res = agt_cb_post_sethook_register((const xmlChar *)”/if:trigger”, sethook_callback_edit);

...

Version 19.10-12 Page 180

Page 181: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

}

The following example code illustrates how Post Set Hook callbacks can be cleaned up. The callbacks cleanup is getting done during Cleanup Phase.

extern void agt_cb_post_sethook_unregister (const xmlChar *defpath);

agt_cb_post_sethook_unregister

Parameter Description

defpath Absolute path expression string indicating which node the callback function is for.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... agt_cb_hook_unregister((const xmlChar *)"/if:trigger");

...}

NOTE:

It is possible to register different callbacks for the same object, for instance, there can be Set Hook and Transaction Hook callbacks registered for the same object, as well as there can be EDIT or GET2 callbacks for the same object. However, in order to cleanup callbacks, unregister them, you need to run different cleanup functions. The EDIT and GET2 callbacks have their own unregister functions and hook-based callbacks have their own unregister function.

Version 19.10-12 Page 181

Page 182: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.3.2 Hooks callback interaction with EDIT2 callbacks (target=candidate)

In case there are multiple Set-Hook and Post Set Hook callbacks registered and the callbacks add several extra edits to the transaction with help of add_edit() API the server will have the following interaction with added edits and normal edits that are coming from PDU. Assume we register Set-Hook callback, Post Set Hook, Set-Order-Hook, Transaction-Hook and EDIT2 callback for the same list object, for example "ietf-interface" module and "/if:interfaces/if:interface" list object. So any time the "interface" list is getting edited the server invokes Set-Hook and Post Set Hook callback and adds up extra "interface" in addition to the regular edit. The following callback invocation order is expected in this case:

Edit on candidate datastore:

1. Transaction Start2. Set Order Hook for "/if:interface[name=vlan1]"3. Set Hook for "/if:interface[name=vlan1]" to add "/if:interface[name=vlan2]"4. Set Order Hook for "/if:interface[name=vlan2]"5. SIL Callback (Validate Phase) for "/if:interface[name=vlan1]"6. Post Set Hook for "/if:interface[name=vlan1]" to add "/if:interface[name=vlan3]"7. SIL Callback (Validate Phase) for "/if:interface[name=vlan2]"8. SIL Callback (Validate Phase) for "/if:interface[name=vlan3]"9. Transaction Complete

Edit on running datastore (after <commit>):

1. Transaction Start2. SIL Callback (Validate Phase) for "/if:interface[name=vlan1]"3. SIL Callback (Validate Phase) for "/if:interface[name=vlan2]"4. SIL Callback (Validate Phase) for "/if:interface[name=vlan3]"5. Validate Complete6. SIL Callback (Apply Phase) for "/if:interface[name=vlan1]"7. SIL Callback (Apply Phase) for "/if:interface[name=vlan2]"8. SIL Callback (Apply Phase) for "/if:interface[name=vlan3]"9. Apply Complete10. SIL Callback (Commit Phase) for "/if:interface[name=vlan1]"11. SIL Callback (Commit Phase) for "/if:interface[name=vlan2]"12. SIL Callback (Commit Phase) for "/if:interface[name=vlan3]"13. Transaction Hook for "/if:interface[name=vlan1]"14. Transaction Hook for "/if:interface[name=vlan2]"15. Transaction Hook for "/if:interface[name=vlan3]"16. Commit/Rollback Complete17. Transaction Complete

Version 19.10-12 Page 182

Page 183: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.3.3 Hooks callback interaction with EDIT2 callbacks (target=running)

Assume the same scenario but the default target in this case is set to <running>. The callbacks invocation order is expectedto be:

1. Transaction Start2. Set Order Hook for "/if:interface[name=vlan1]"3. Set Hook for "/if:interface[name=vlan1]" to add "/if:interface[name=vlan2]"4. Set Order Hook for "/if:interface[name=vlan2]"5. SIL Callback (Validate Phase) for "/if:interface[name=vlan1]"6. Post Set Hook for "/if:interface[name=vlan1]" to add "/if:interface[name=vlan3]"7. SIL Callback (Validate Phase) for "/if:interface[name=vlan2]"8. SIL Callback (Validate Phase) for "/if:interface[name=vlan3]"9. SIL Callback (Apply Phase) for "/if:interface[name=vlan1]"10. SIL Callback (Apply Phase) for "/if:interface[name=vlan2]"11. SIL Callback (Apply Phase) for "/if:interface[name=vlan3]"12. SIL Callback (Commit Phase) for "/if:interface[name=vlan1]"13. SIL Callback (Commit Phase) for "/if:interface[name=vlan2]"14. SIL Callback (Commit Phase) for "/if:interface[name=vlan3]"15. Transaction Hook for "/if:interface[name=vlan1]"16. Transaction Hook for "/if:interface[name=vlan2]"17. Transaction Hook for "/if:interface[name=vlan3]"18. Transaction Complete

In case default target is set to <running> there is an option to control callback invocation for added edits with help of a newagt_val_add_edit_max() API:

/********************************************************************* FUNCTION agt_val_add_edit_max** Create a new edit based on edit_value.* if its NULL or invalid the error will be generated.** Move or insertion OP available.* Skip callbacks for added edits option is available.** Only allowed for Set Hooks or Post Set Hook, the rest are ignored.** INPUTS:* txcb == transaction in progress* defpath == XPath path of object instance* edit_value == val_value_t representing newnode in transaction* only needed for create, merge, replace, not delete** edit_operation == <operation string>* "create"* "delete"* "insert"* "merge"* "move"* "replace"* "remove"** insert_where == <insert enum string>

Version 19.10-12 Page 183

Page 184: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* "before"* "after"* "first"* "last"* Will be used only if the operations are "move" or "insert".* Ignored otherwise.** insert_point == is a XPath encoded string like the defpath. Only for* 'before' or 'after' insert_where paramter. The insert_where* must be set to 'before' or 'after' if insert_point specified.* Will be used only if the operations are "move" or "insert".* Ignored otherwise.* E.g: "/test3[string.1='entry2'][uint32.1='2']"** skip_cb == TRUE if DO NOT invoke callbacks for an edded edit if any.* FALSE if SKIP any callback for added edit* including Transaction, EDIT1, EDIT2 callbacks* Only when target=running** RETURNS:* status**********************************************************************/extern status_t agt_val_add_edit_max (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, const xmlChar *defpath, val_value_t *edit_value, const xmlChar *edit_operation, const xmlChar *insert_where, const xmlChar *insert_point, boolean skip_cb);

With help of this API the serer can be told to whether it should invoke callbacks for added edits.

If skip_cb parameter is set to TRUE then the server will not invoke any callback for added edits. That's the callback order will look as follows. Assume the same scenario but the default target in this case is set to <running>. The callbacks invocation order is expected to be:

1. Transaction Start2. Set Order Hook for "/if:interface[name=vlan1]"3. Set Hook for "/if:interface[name=vlan1]" to add "/if:interface[name=vlan2]"4. Set Order Hook for "/if:interface[name=vlan2]"5. SIL Callback (Validate Phase) for "/if:interface[name=vlan1]"6. Post Set Hook for "/if:interface[name=vlan1]" to add "/if:interface[name=vlan3]"7. SIL Callback (Apply Phase) for "/if:interface[name=vlan1]"8. SIL Callback (Commit Phase) for "/if:interface[name=vlan1]"9. Transaction Hook for "/if:interface[name=vlan1]"10. Transaction Complete

NOTE:

Skip_cb parameter can be used only when the default target <running>. Otherwise; the server always invoke callback for added edits in case the default target is <candidate>.

Version 19.10-12 Page 184

Page 185: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.4 Transaction Hook Callback

A Transaction Hook is a function that is invoked within the transaction when an object is modified. The Transaction Hook is similar to the Set Hook except this callback is invoked just before the data is committed to the running datastore. This callback will be invoked after EDIT1 or EDIT2 callbacks for the same object. Note that the Transaction hook is not allowed to change anything, It is not allowed to call agt_val_add_edit, or to alter the edits or the datastore in any way. Manipulation with datastore are only allowed for Set Hook callbacks. If Transaction Hook callbacks calls agt_val_add_edit, the operation will be ignored. Do not return error just ignore add_edit calls.

The following function template definition is used for Transaction Hook callback functions:

/* Typedef of the agt_hook_cb callback */typedef status_t

(*agt_cb_hook_t)(ses_cb_t *scb, rpc_msg_t *msg,

agt_cfg_transaction_t *txcb, op_editop_t editop,

val_value_t *newval, val_value_t *curval);

Callback Template

• Type: User Callback

• Max Callbacks: 1 Transaction Hook callback per object

• File: agt_cb.h

• Template: agt_cb_hook _t

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ txcb == transaction control block in progress

▪ editop == edit operation enumeration for the node being edited

▪ newval == value holding the proposed changes to apply to the current config, depending on the editop value.

▪ curval == current values from the <running> or <candidate> configuration, if any. Could be NULL for create and other operations.

◦ Outputs: none

◦ Returns: status_t:Status of the callback function execution

• Register: agt_cb_hook_register

• Unregister: agt_cb_hook_unregister

Version 19.10-12 Page 185

Page 186: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.4.1 Transaction Hook Callback Initialization and Cleanup

A Transaction Hook database edit callback function is hooked into the server with the agt_cb_hook_register function, described below.

The agt_cb_hook_register function is used to declare the callback as a specific style callback. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

NOTE:

The Transaction Hook callbacks will not be invoke during explicit validate command and in case --sil-skip-load netconfd-pro parameters is set to TRUE

Initialization function with the registration of Transaction Hook callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ... /* Register an object specific Transaction Hook callback */ res = agt_cb_hook_register((const xmlChar *)”/if:trigger”,

AGT_HOOKFMT_NODE, AGT_HOOK_TYPE_TRANSACTION, sethook_callback_edit);

...}

agt_cb_hook_register

Parameter Description

defpath Absolute path expression string indicating which node the callback function is for.

format different hook formats dictates specific hook functionality

type different hook types dictates hook invocation point

cbfn address of callback function to use

Version 19.10-12 Page 186

Page 187: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.4.2 Transaction Hook Callback Function Example

The following sections illustrates how to utilize the Transaction Hook callback in examples.

NOTE:

Manipulation with datastore are only allowed for Set Hook or Post Set Hook callbacks. If Transaction Hook or other In-Transaction callbacks call add_edit() the operation will be ignored. It will not return an error, just ignore add_edit calls.

Consider the same data model as for the previous examples; however, now we will register Transaction Hook callback for the top level /if:interfaces container element. In this example, we will validate the container node.

Now, whenever the 'interfaces' node is edited, the callback function will be called and perform specific validation actions.

The callback function may look as follows:

/******************************************************************** * FUNCTION transhook_callback* * Callback function for server object handler * Used to provide a callback for a specific named object * * Transaction-Hook: * trigger: DELETE /interface* effect: * - if testval node exist the CREATE operation will be denied * - if testval is ‘deny-delete’, the operation will be denied * ********************************************************************/ static status_t transhook_callback (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval) { log_debug("\nEnter Transaction-Hook callback");

status_t res = NO_ERR; status_t res2 = NO_ERR; val_value_t *errorval = (curval) ? curval : newval;

const xmlChar *defpath =(const xmlChar *)"/if:interfaces/if:status";

/* find a test node and validate its value */ val_value_t *testval = agt_val_get_data(txcb->cfg_id,

defpath, &res2);

switch (editop) { case OP_EDITOP_LOAD: break;

Version 19.10-12 Page 187

Page 188: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

case OP_EDITOP_MERGE: case OP_EDITOP_REPLACE: case OP_EDITOP_CREATE:

/* deny an edit, if the test exist */ if (testval) { res = ERR_NCX_ACCESS_DENIED; } break; case OP_EDITOP_DELETE:

/* deny an edit, if the test value set to “deny-delete” */ if (testval && !xml_strcmp(VAL_STR(testval), (const xmlChar *)"deny-delete") {

res = ERR_NCX_ACCESS_DENIED; } else { res2 = NO_ERR; } break; default: res = SET_ERROR(ERR_INTERNAL_VAL); }

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_CONTENT, res, NULL, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* hooks_transhook_edit */

NOTE:

Manipulation with datastore are only allowed for Set Hook or Post Set Hook callbacks. If Transaction Hook callbacks call add_edit() the operation will be ignored. It will not return an error, just ignore add_edit calls.

So whenever some north bound agent edits an /if:interfaces node the callback is invoked and additionally validates the /if:interfaces/if:status node. Based on this validation, the operation can be denied.

Version 19.10-12 Page 188

Page 189: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.5 Transaction Start Callback

The Transaction Start function is the user/system callback that is invoked before any changes to the candidate database will be committed.

The following function template definition is used for Transaction Start callback functions:

/* Typedef of the trans_start callback */typedef status_t (*agt_cb_trans_start_t)(agt_cfg_transaction_t *txcb);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_trans_start_t

◦ Inputs:

▪ txcb == transaction control block in progress

• Outputs: none

• Returns: status_t:

Status of the callback function execution. If an error is returned the transaction will be terminated.

• Register: agt_cb_trans_start_register

• Unregister: agt_cb_trans_start_unregister

Version 19.10-12 Page 189

Page 190: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.5.1 Transaction Start Callback Initialization and Cleanup

The Transaction Start callback function is hooked into the server with the agt_cb_trans_start_register function, described below.

extern status_t agt_cb_trans_start_register (agt_cb_trans_start_t cbfn);

The register function is used to declare a specific callback function for Transaction Start callbacks. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the registration of the Transaction Start callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* Register a Transaction Start callback. */ res = agt_cb_trans_start_register(transaction_start); if (res != NO_ERR) { return res; }

...}

The following example code illustrates how the callback can be cleaned up. The callback cleanup is getting done during module Cleanup Phase.

extern void agt_cb_trans_start_unregister (agt_cb_trans_start_t cbfn);

extern void agt_cb_trans_complete_unregister (agt_cb_trans_complete_t cbfn);

Version 19.10-12 Page 190

Page 191: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ...

/* Unregister a Transaction Start callback */ agt_cb_trans_start_unregister(transaction_start);

/* Unregister a Transaction Complete callback */ agt_cb_trans_complete_unregister(transaction_complete);

...}

6.5.2 Transaction Start Callback Function Examples

The following sections illustrates how to utilize the Transaction Start callback in examples.

In this example, the Transaction Start callback function applies multiple actions prior the transaction is actually started. The purpose of this function is to provide more validation options and more flexible and easier development. This callback function may deny the start of the transaction if some specific check is unmet, in this example, if the node “trigger” is present in the datastore then the server will deny the transaction. In addition, in this example, the callback function updates a comment string of this transaction, it may send a custom notifications, or write a system or other log entries.

The following example code illustrates how the Transaction Start callback may look like.

/******************************************************************** * FUNCTION transaction_start * * Start Transaction callback * The Start Transaction function is the user/system * callback that is invoked before any changes to the * candidate database will be committed. * * INPUTS: * txcb == transaction control block in progress * * RETURNS: * status ********************************************************************/ static status_t transaction_start (agt_cfg_transaction_t *txcb) {

log_debug("\nEnter transaction_start callback"); status_t res = NO_ERR;

/* deny the start of transaction if some specific check is unmet. E.g:

Version 19.10-12 Page 191

Page 192: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

* if there is a specific node present in the datastore */ val_value_t *val = agt_val_get_data(txcb->cfg_id, (const xmlChar *)"/if:trigger", &res); if (val) { res = ERR_NCX_ACCESS_DENIED; }

/* update a comment string of this transaction */ txcb->comment = (const xmlChar *)"special transaction";

/* send custom notifications */

/* write a sys, audit, vendor specific, etc log entries */

return res;

} /* transaction_start */

NOTE:

Manipulation with datastore are only allowed for Set Hook or Post Set Hook callbacks. If Transaction Start or Complete callbacks call add_edit() the operation will be ignored. It will not return an error, just ignore add_edit calls.

Version 19.10-12 Page 192

Page 193: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.6 Transaction Start SA Callback

The Transaction Start SA function is the sub-agent user/system callback that is invoked right before the transaction is started.

The server sends “server request” message to SIL-SA subsystems that registered callbacks right before the transaction is started. Once the SIL-SA subsystems receive the “server-message” Transaction Start SA they will invoke the callbacks. After the callbacks are invoked and if they are successful then subsystem responds with the “ok” message. If the callbacks are not invoked due to some reason or if the callbacks return error then an “error” message is returned to the server causing the server transaction termination.

The following function template definition is used for Transaction Start SA callback functions:

/* Typedef of the trans_start callback */typedef status_t (*agt_cb_sa_trans_start_t) (const xmlChar *transaction_id, boolean isvalidate, boolean isrollback, boolean isrunning);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_sa_trans_start_t

◦ Inputs:

▪ transaction_id == transaction ID of the transaction control block in progress

▪ isvalidate == TRUE if this is Transaction is for Validate operation

▪ isrollback == TRUE if this is Transaction for a Rollback Phase or Load

▪ isrunning == if transaction is for the running datastore

• Outputs: none

• Returns: status_t:

Status of the callback function execution. If an error is returned the transaction will be terminated.

• Register: agt_cb_sa_trans_start_register

• Unregister: none

6.6.1 Transaction Start SA Callback Initialization and Cleanup

The Transaction Start SA callback function is hooked into the server with the agt_cb_sa_trans_start_register function, described below.

Version 19.10-12 Page 193

Page 194: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

extern status_t agt_cb_sa_trans_start_register (agt_cb_sa_trans_start_t cbfn);

The register function is used to declare a specific callback function for Transaction Start SA callbacks. For SIL-SA the registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configurationdatabase and before running configurations are loaded.

Initialization function with the registration of the Transaction Start SA callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* Register a Transaction Start callback. */ res = agt_cb_sa_trans_start_register(transaction_start); if (res != NO_ERR) { return res; }

...}

The SIL-SA version of the Transaction Start SA callback does not have any unregister functions. The callback will be cleaned up automatically whether when the subsystem goes away or when the server shuts down.

Version 19.10-12 Page 194

Page 195: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.6.2 Transaction Start SA Callback Function Examples

The following sections illustrates how to utilize the Transaction Start SA callback in examples.

In this example, the Transaction Start SA callback function applies multiple actions after the transaction is actually completed. The purpose of this function is to provide more validation options and more flexible and easier development. This callback function may deny the start of the transaction if some specific check is unmet.

In this example, if the transaction is for the <validate> operation on <running> datastore then the SIL-SA callback will trigger an error and deny the server transaction. In addition, in this example, the callback function can send a custom notifications, or write a system or other log entries.

The following example code illustrates how the Transaction Start SA callback may look like.

/********************************************************************* FUNCTION silsa_transaction_start** Start Transaction SA callback* The Start Transaction function is the user/system* callback that is invoked before any changes to the* database will be committed.** RETURNS:* status********************************************************************/static status_t silsa_transaction_start (const xmlChar *transaction_id_val, boolean isvalidate_val, boolean isrollback_val, boolean isrunning_val){ if (!transaction_id_val) { log_error("\ntransaction_id value not set"); return ERR_INTERNAL_VAL; }

const xmlChar *user = sil_sa_get_username(); const xmlChar *client_addr = sil_sa_get_client_addr();

if (LOGDEBUG2) { log_debug2("\n\n********************************************" "\nEnter silsa_transaction_start callback for silsa-test " "---- 2" "\ntransaction_id -- %s" "\nuser_id -- %s" "\nclient_addr -- %s" "\nisvalidate -- %s" "\nisrollback -- %s" "\nisrunning -- %s" "\n********************************************\n\n", transaction_id_val, user, client_addr, isvalidate_val ? NCX_EL_TRUE : NCX_EL_FALSE, isrollback_val ? NCX_EL_TRUE : NCX_EL_FALSE, isrunning_val ? NCX_EL_TRUE : NCX_EL_FALSE); }

Version 19.10-12 Page 195

Page 196: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* return an error when "validate" operation is in progress */ if (!isrollback_val && isvalidate_val && isrunning_val) { return ERR_NCX_INVALID_NUM; } else { return NO_ERR; }

} /* silsa_transaction_start */

In the example above, the callback simply logs all the available parameters and dynies the transaction is it is for <validate> operation on running datastore and return “Invalid Number” error status, as an example.

In this callback, there could be handling for customer specific pointers, it is a good place to initialize specific pointers that will be cleaned after the transaction complete during the Transaction Complete SA callback invocation.

In the example, we used two additional APIs to retrieve current transaction “user name” and “address”:

/* Get the user_id value from the message header */ const xmlChar *user = sil_sa_get_username();

/* Get the client address (client_addr value from the message header) */const xmlChar *client_addr = sil_sa_get_client_addr();

These two APIs only available in the SIL-SA version of the SIL code and intended to provide an access to specific fields in the message header since the message header itself is not available in the SIL-SA version of of the SIL.

Version 19.10-12 Page 196

Page 197: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.7 Transaction Complete Callback

The Transaction Complete function is the user/system callback that is invoked after the transactions has been processed.

The following function template definition is used for Transaction Complete callback functions:

/* Typedef of the trans_complete callback */ typedef void (*agt_cb_trans_complete_t)(agt_cfg_transaction_t *txcb)

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_trans_complete_t

◦ Inputs:

▪ txcb == transaction control block to check

• Outputs: none

• Returns: none

• Register: agt_cb_trans_complete_register

• Unregister: agt_cb_trans_complete_unregister

Version 19.10-12 Page 197

Page 198: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.7.1 Transaction Complete Callback Initialization and Cleanup

The Transaction Complete callback function is hooked into the server with the agt_cb_trans_complete_register function, described below.

extern status_t agt_cb_trans_complete_register (agt_cb_trans_complete_t cbfn);

The register function is used to declare a specific callback function for Transaction Complete callbacks. The registration isdone during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the registration of the Transaction Complete callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ... /* Register a Transaction Complete callback. */ res = agt_cb_trans_complete_register(transaction_complete); if (res != NO_ERR) { return res; }

...}

Version 19.10-12 Page 198

Page 199: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.7.2 Transaction Complete Callback Function Example

The following sections illustrates how to utilize the Transaction Complete callback in examples.

In this example, the Transaction Complete callback function applies multiple actions prior the transaction is actually completed. The purpose of this function is to provide more validation options and more flexible and easier development. This callback function may send a custom notifications, or write a system or other log entries.

The following example code illustrates how the Transaction Complete callback may look like.

/******************************************************************** * FUNCTION transaction_complete* * Complete Transaction callback* The Transaction Complete function is the* user/system callback that is invoked after* the transactions has been processed. * * INPUTS: * txcb == transaction control block in progress * * RETURNS: * status ********************************************************************/ static status_t transaction_complete (agt_cfg_transaction_t *txcb) {

log_debug("\nEnter transaction_complete callback");

/* send custom notifications */

/* write a sys, audit, vendor specific, etc log entries */

return res;

} /* transaction_complete */

Version 19.10-12 Page 199

Page 200: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.8 Transaction Complete SA Callback

The Transaction Complete SA function is the user/system callback that is invoked after the transactions has been processed.

After the transaction is completed the server will send “server-event” to notify subsystems that the Transaction Complete SA callbacks should be invoked. During this process the server checks if a subsystem has any callbacks to be invoked and sends a “server-event” message to the subsystem if it has registered Transaction Complete SA callback(s). Once the SIL-SA subsystem receives the “server-event” for Transaction Complete SA callbacks it will invoke the callbacks.

The server does not expect that SIL-SA subsystems reply to the “server-event” message.

The following function template definition is used for Transaction Complete SA callback functions:

/* Typedef of the trans_start SA callback */typedef status_t (*agt_cb_sa_trans_start_t) (const xmlChar *transaction_id);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_sa_trans_complete_t

◦ Inputs:

▪ transaction_id == transaction ID of the transaction control block in progress

• Outputs: none

• Returns: none

• Register: agt_cb_trans_complete_register

• Unregister: none

Version 19.10-12 Page 200

Page 201: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.8.1 Transaction Complete SA Callback Initialization and Cleanup

The Transaction Complete SA callback function is hooked into the server with the agt_cb_sa_trans_complete_register function, described below.

extern status_t agt_cb_sa_trans_complete_register (agt_cb_sa_trans_start_t cbfn);

The register function is used to declare a specific callback function for Transaction Complete SA callbacks. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configurationdatabase and before running configurations are loaded.

Initialization function with the registration of the Transaction Complete SA callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* Register a Transaction Complete callback. */ res = agt_cb_sa_trans_complete_register(transaction_complete); if (res != NO_ERR) { return res; }

...}

The SIL-SA version of the Transaction Complete SA callback does not have any unregister functions. The callback will becleaned up automatically whether when the subsystem goes away or when the server shuts down.

Version 19.10-12 Page 201

Page 202: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.8.2 Transaction Complete SA Callback Function Example

The following sections illustrates how to utilize the Transaction Complete SA callback in examples.

In this example, the Transaction Complete SA callback function applies multiple actions after the transaction is actually completed. The purpose of this function is to provide more validation options and more flexible and easier development.

The following example code illustrates how the Transaction Complete SA callback may look like.

/********************************************************************* FUNCTION silsa_transaction_complete** Complete Transaction callback* The Complete Transaction function is the user/system* callback that is invoked at the end of the transaction*** Max Callbacks: Unlimited** INPUTS:* transaction_id_val == transaction id** RETURNS:* none********************************************************************/static void silsa_transaction_complete (const xmlChar *transaction_id_val){

if (!transaction_id_val) { log_error("\ntransaction_id value not set"); return; } /* This might run some cleanup of values that were set during the Transaction * Start callback */

return res;

} /* silsa_transaction_complete */

In this callback, there could be handling for customer specific pointers, it is a good place to cleanup specific pointers that were registered/created during the Transaction Start SA callback invocation.

Version 19.10-12 Page 202

Page 203: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.9 Set Order Hook Callback

The Set Order Hook callback function is the user/system callback that is used to provide an access for a specific list instance object and modify its secondary SIL priority.

The Set Order Hook is invoked in document order for each edited instance of the specified object. The callback returns thedesired secondary SIL priority for the specific list instance. This callback is invoked once per edited instance and after any Set Hook is called for the object and instance.

The following function template definition is used for Set Order Hook callback functions:

/* Typedef of the callback */ typedef uint8 (*agt_cb_order_hook_t) (agt_cfg_transaction_t *txcb,

op_editop_t editop, val_value_t *newval,

val_value_t *curval, status_t *res);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per object

• File: agt_cb.h

• Template: agt_cb_order_hook_t

◦ Inputs:

▪ txcb == transaction control block to check

▪ editop == edit operation enumeration for the node being edited

▪ newval == value holding the proposed changes to apply to the current config, depending on the editop value.

▪ curval == current container values from the <running> or <candidate> configuration, if any. Could be NULL for create and other operations.

▪ res == address of return status

• Outputs: status of callback; status == error will cause the transaction to be terminated and rollback started

• Returns: the secondary SIL priority to assign to the object instance

• Register: agt_cb_order_hook_register

• Unregister: agt_cb_order_hook_unregister

Version 19.10-12 Page 203

Page 204: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.9.1 Set Order Hook Callback Initialization and Cleanup

The Set Order Hook callback function is hooked into the server with the agt_cb_order_hook_register function, describedbelow.

extern status_t agt_cb_order_hook_register (const xmlChar *defpath, agt_cb_order_hook_t cbfn);

The register function is used to declare a specific callback function for the Set Order Hook callback. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the registration of the Set Order Hook callback may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* Register an object specific Set-Order-Hook callback function */ res = agt_cb_order_hook_register((const xmlChar*)"/if:interface/if:interface",

set_order_hook); if (res != NO_ERR) { return res; }

...}

Now, whenever the /if:interface/if:interface list is getting modified, the callback function will be invoked and desired secondary SIL priority for the list instance can be specified. As a result, the server will apply list of edits based on this priority, the lower priority number is set to the instance the earlier the server will apply the edit.

The following example code illustrates how the callbacks can be cleaned up.

extern void agt_cb_order_hook_unregister (const xmlChar *defpath);

The callbacks cleanup is getting done during module Cleanup Phase.

Version 19.10-12 Page 204

Page 205: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ...

/* Unregister an object specific Set-Order-Hook callback function */ agt_cb_order_hook_unregister((const xmlChar*)"/if:interface/if:interface");

...}

Version 19.10-12 Page 205

Page 206: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.9.2 Set Order Hook Callback Function Examples

The following sections illustrates how to utilize the Set Order Hook callback in examples.

The Set Order Hook callback function is the user/system callback that is used to provide an access for a specific list instance object and modify its secondary SIL priority.

NOTE:

The Set Order Hook callback function can be registered only for “list” YANG objects.

In this example, the Set Order Hook callback function applies priority to a list edit based on a key value. The purpose of this function is to prioritize edits and give more flexible and easier development.

The following example code illustrates how the Set Order Hook callback may look like:

/******************************************************************** * FUNCTION set_order_hook * * Callback function is* used to provide a callback for a specific named object * * This callback is invoked once per instance before any * Set Hook or Post Set Hook is called for the object and instance. * * INPUTS: * txcb == transaction control block in progress * editop == edit operation enumeration for the node being edited * newval == container object holding the proposed changes to * apply to the current config, depending on * the editop value. Will not be NULL. * curval == current container values from the <running> * or <candidate> configuration, if any. Could be NULL * for create and other operations. * res == address of return status * OUTPUTS: * *res == status of callback; status == error will cause the * transaction to be terminated and rollback started * RETURNS: * the secondary SIL priority to assign to the object instance ********************************************************************/ static uint8 set_order_hook (agt_cfg_transaction_t *txcb, op_editop_t editop, val_value_t *newval, val_value_t *curval, status_t *res) { (void)txcb; (void)editop; (void)curval;

uint8 retprior = 0;

Version 19.10-12 Page 206

Page 207: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* Set the priority only if the operation is not delete and if * a new value has keys, that will be compared later */ if (newval && val_has_index(newval)) {

/* Get the first index entry, if any for this value node */ const val_index_t *c1 = val_get_first_index(newval); if (!c1) {

return ERR_INTERNAL_VAL; }

if (!xml_strcmp(VAL_STR(c1->val), (const xmlChar *)"vlan1")) { log_debug("\n Setting Priority to 140 for index:%s \n", VAL_STR(c1->val));

retprior = 100; } else if (!xml_strcmp(VAL_STR(c1->val), (const xmlChar *)"ethernet1/1/10")) { log_debug("\n Setting Priority to 160 for index:%s \n", VAL_STR(c1->val));

retprior = 150; } else { log_debug("\n Setting Priority to 130 for index:%s \n", VAL_STR(c1->val));

retprior = 200; } }

return retprior;

} /* set_order_hook */

So, whenever some north bound agent edits an /if:interfaces/if:interface node the callback is invoked and additionally assigns desired priority to this edit. Note, that in the example above, the priority will be assigned only if there is a new value. It will be assigned only if the edit operation is not “delete” or “remove” because during the edits for those operations the server does not allocate a new value. Use a current value for any comparisons or validations during “delete” or “remove” edit operations.

To exemplify, if the north bound agent is creating 3 interfaces with different key values at the same time using the following<edit-config> RPC:

<edit-config> <target> <candidate/> </target> <default-operation>merge</default-operation> <test-option>set</test-option> <config> <interfaces>

<interface> <name>ethernet1/1/1</name>

</interface>

<interface> <name>vlan1</name>

Version 19.10-12 Page 207

Page 208: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

</interface>

<interface> <name>ethernet1/1/10</name>

</interface> </interfaces> </config> </edit-config>

By the regular server logic, the server would validate/apply/commit these interfaces in order they are specified in the edit. However, using the Set Order Hook the server now will apply these “interfaces” based on their priority assigned in the callback function. The first list instance that will be processed by the server will be the “interface” with the key value set to “vlan1” since it has the highest priority - “100”.

So, the edits order would look as follows, from the server's logging:

***** start commit phase on candidate for session 5, transaction 1234358 ***** Start full commit of transaction 1234358: 3 edits on candidate config edit-transaction 1234358: on session 5 by --@::1 message-id: -- trace-id: -- datastore: candidate operation: create target: /if:interfaces/if:interface[if:name="vlan1"] comment: none

edit-transaction 1234358: on session 5 by --@::1 message-id: -- trace-id: -- datastore: candidate operation: create target: /if:interfaces/if:interface[if:name="ethernet1/1/10"] comment: none

edit-transaction 1234358: on session 5 by --@::1 message-id: -- trace-id: -- datastore: candidate operation: create target: /if:interfaces/if:interface[if:name="ethernet1/1/1"] comment: none

The Set Order Hook callback can be extremely useful in cooperation with the Set Hook or Post Set Hook callback or by itself. The power to prioritize all the edits in the transaction provides wide spectrum of utilization. The fact that the Set Order Hook is getting invoked before SIL or any other callbacks for the same object provides possibility to customize the transaction as desired.

Version 19.10-12 Page 208

Page 209: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.10 Add Edit API

The Add Edit API is used to add an edit to the transaction in progress.

Manipulation with datastore are only allowed for Set Hook or Post Set Hook callbacks. If Transaction Hook or Start/Complete Transaction callbacks call add_edit() the operation will be ignored. Do not return error just ignore add_edit calls.

The following function template definition is used for Add Edit API callback functions:

/* FUNCTION agt_val_add_edit */status_t

agt_val_add_edit(ses_cb_t *scb, rpc_msg_t *msg,

agt_cfg_transaction_t *txcb, const xmlChar *defpath, val_value_t *edit_value, op_editop_t editop);

API Template

• Type: Server Utility Function

• File: agt_val.h

• Template: agt_val_add_edit

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ txcb == transaction control block in progress

▪ defpath == XPath expression specifying the data instance to add

▪ edit_value == string containing the XML or JSON value to use in the edit. Can be NULL if editop is OP_EDITOP_DELETE or OP_EDITOP_REMOVE

▪ editop == edit operation enumeration for the edit being added

◦ Outputs: none

◦ Returns: status_t:Status of the operation;

Version 19.10-12 Page 209

Page 210: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.11 Add Edit Extended API

The Add Edit Extended API is used to insert or move new list or leaf-list entries to the transaction in progress.

Manipulation with datastore are only allowed for Set Hook or Post Set Hook callbacks. If Transaction Hook or Start/Complete Transaction callbacks call add_edit_ex() the operation will be ignored. Do not return error just ignore add_edit_ex calls.

The following function template definition is used for Add Edit Extended API callback functions:

/* FUNCTION agt_val_add_edit_ex */status_t agt_val_add_edit_ex (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, const xmlChar *defpath, val_value_t *edit_value, const xmlChar *edit_operation, const xmlChar *insert_where, const xmlChar *insert_point)

API Template

• Type: Server Utility Function

• File: agt_val.h

• Template: agt_val_add_edit

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ txcb == transaction control block in progress

▪ defpath == XPath expression specifying the data instance to add

▪ edit_value == val_value_t representing newnode in transaction only needed for create, merge, replace, insert. Ignored for delete or remove

▪ edit_operation == <operation string> E.g.: "create" "delete" "insert" "merge" "move" "replace" "remove"

▪ insert_where == <insert enum string>. Will be used only if operations are "move" or "insert". Ignored otherwise.

E.g.: "before" "after" "first" "last"▪ insert_point == is a XPath encoded string like the defpath. Only for “before” or “after” insert_where

parameter. The insert_where must be set to “before” or “after” if insert_point specified. Will be used only if the operations are "move" or "insert". Ignored otherwise.

E.g: "/test3[string.1='entry2'][uint32.1='2']"◦ Outputs: none

◦ Returns: status_t:Status of the operation;

Version 19.10-12 Page 210

Page 211: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

NOTE:

The server does not support the "insert" and "move" operation on the nodes that are being modified at the same transaction at the same time. That's if the server already has an undo record (an edit on specific node), then the "insert" or "move" add_edit_ex() API on the same specific node will return an error. The server will only insert a new nodes and move only existent nodes. It will not move a new nodes or a nodes that are being already modified.

Version 19.10-12 Page 211

Page 212: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.12 Add Edit Maximum API

The Add Edit maximum API is used to insert or move new list or leaf-list entries to the transaction in progress and also controls whether the server should invoke callbacks for added edits or not.Manipulation with datastore are only allowed for Set Hook or Post Set Hook callbacks. If Transaction Hook or Start/Complete Transaction callbacks call add_edit_ex() or _max the operation will be ignored. Do not return error just ignore add_edit_ex or _max calls.

The following function template definition is used for Add Edit Maximum API callback functions:

/* FUNCTION agt_val_add_edit_max */status_t agt_val_add_edit_max (ses_cb_t *scb, rpc_msg_t *msg, agt_cfg_transaction_t *txcb, const xmlChar *defpath, val_value_t *edit_value, const xmlChar *edit_operation, const xmlChar *insert_where, const xmlChar *insert_point, boolean skip_cb);

API Template

• Type: Server Utility Function

• File: agt_val.h

• Template: agt_val_add_edit_max

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ txcb == transaction control block in progress

▪ defpath == XPath expression specifying the data instance to add

▪ edit_value == val_value_t representing newnode in transaction only needed for create, merge, replace, insert. Ignored for delete or remove

▪ edit_operation == <operation string> E.g.: "create" "delete" "insert" "merge" "move" "replace" "remove"

▪ insert_where == <insert enum string>. Will be used only if operations are "move" or "insert". Ignored otherwise.

E.g.: "before" "after" "first" "last"▪ insert_point == is a XPath encoded string like the defpath. Only for “before” or “after” insert_where

parameter. The insert_where must be set to “before” or “after” if insert_point specified. Will be used only if the operations are "move" or "insert". Ignored otherwise.

E.g: "/test3[string.1='entry2'][uint32.1='2']"▪ skip_cb ==TRUE if DO NOT invoke callbacks for an edded edit if any. FALSE if SKIP any callback for

added edit including Transaction, EDIT1, EDIT2 callbacks. Only when --target=running.◦ Outputs: none

Version 19.10-12 Page 212

Page 213: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

◦ Returns: status_t:Status of the operation;

NOTE:

The server does not support the "insert" and "move" operation on the nodes that are being modified at the same transaction at the same time. That's if the server already has an undo record (an edit on specific node), then the "insert" or "move" add_edit_ex() or add_edit_max() API on the same specific node will return an error. The server will only insert a new nodes and move only existent nodes. It will not move a new nodes or a nodes that are being already modified.

NOTE:

Skip_cb parameter can be used only when the default target <running>. Otherwise; the server always invoke callback for added edits in case the default target is <candidate>.

Version 19.10-12 Page 213

Page 214: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.13 Get Data API

The Get Data API is used to retrieve data nodes from the server.

If the XPath expression matches multiple nodes, then only the first instance is returned. The exact instance is implementation-dependent if the data is “ordered-by system”.

The following function template definition is used for Get Data API callback functions:

/* FUNCTION agt_val_get_data */const val_value_t *

agt_val_get_data (ncx_cfg_t cfgid, const xmlChar *defpath, status_t *retres);

API Template

• Type: Server Utility Function

• File: agt_val.h

• Template: agt_val_get_data

◦ Inputs:

▪ cfgid == datastore enumeration to use (candidate or running)

▪ defpath == XPath expression specifying the data instance to add

▪ retres == address of return status

◦ Outputs:

▪ *retres == set to the return status

◦ Returns: const *val_value_t

▪ Read only pointer to the requested data

▪ Data cannot be saved and used later, can only be used immediately after the call to agt_val_get_data

▪ ERR_INTERNAL_MEM can be returned if a malloc fails

▪ ERR_NCX_DEF_NOT_FOUND can be returned if the XPath expression contains unknown or ambiguousobject names

Version 19.10-12 Page 214

Page 215: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.14 Startup Hook Callback

The Startup Hook function is the user/system callback that is invoked before any changes done to the <startup> datastore.It is invoked only if the <startup> capability is enabled.

The Startup Hook callback is invoked before any modifications to the <startup> datastore during <edit-config>, <copy-config> and <delete-config> operation. This callback is not limited hence any number of callbacks can be registered.

If an application needs to perform additional validations, check or any other actions before the <startup> datastore is modified or accessed, this new Startup Hook can be used.

The callback will be called for the following operations:

• Any <edit-config> if the --target=running and <startup> is enabled

• After <commit> operation if --target=candidate and <startup> is enabled

• After <copy-config> if the target of the copying is the <startup> datastore

• <delete-config> if the target of deletion is <startup> datastore and the <startup> datastore is enabled.

Below CLI parameters can effect the callback invocation:

• --with-startup=true : <copy-config> and <delete-config> will invoke the callbacks

• --with-startup=false : <copy-config> and <delete-config> will NOT invoke the callbacks.

If the callback fails then no further actions will be executed and the server would reply with the error.

The following function template definition is used for Startup Hook callback functions:

/* Typedef of the startup_hook callback */typedef status_t

(*agt_cb_startup_hook_t)(ses_cb_t *scb, rpc_msg_t *msg, cfg_template_t source_config, cfg_template_t target_config);

Callback Template:

• Type: User Callback

• Max Callbacks: No limit

• File: agt_cb.h

• Template: agt_cb_startup_hook

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ source == datastore which is being copied

▪ target == datastore which is being edited

• Outputs: none

• Returns: Status of the callback function execution

Version 19.10-12 Page 215

Page 216: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

• Register: agt_cb_startup_hook_register

• Unregister: agt_cb_startup_hook_unregister

6.14.1 Startup Hook Callback Initialization and Cleanup

The Startup Hook callback is object independent and module independent callback which means there is no need to link it to the specific object as it is done for EDIT or GET callbacks.

The Startup Hook callback function is hooked into the server with the agt_cb_startup_hook_register function, as described below.

The registration is done during the Initialization Phase 1. Initialization function with the registration of the Startup Hook callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* register startup hook callback */ res = agt_cb_startup_hook_register(startup_hook_callback); if (res != NO_ERR) { return res; }

...}

agt_cb_startup_hook_register

Parameter Description

cbfn The callback function address. This function will be used for the callback invocation

Now whenever the <startup> is being modified the startup_hook_callback function is called and provide access to sourcedatastore and the startup datastore. If there are multiple callbacks registered, all the callbacks are called one after the other.

The below code illustrates how the callbacks are unregistered or cleaned up:

Version 19.10-12 Page 216

Page 217: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ...

/* Unregister startup hook callback */ agt_cb_startup_hook_unregister(startup_hook_callback);

...}

agt_cb_startup_hook_unregister

Parameter Description

cbfn The callback function address. This function will be used for the callback invocation

Version 19.10-12 Page 217

Page 218: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.14.2 Startup Hook Callback Examples

The following sections illustrates how to utilize the Startup Hook callback in examples.

The Startup Hook callback is called just before the <startup> is being modified.

The purpose of this function is to give more flexible and easier development for users. In case there is a need to access the <startup> datastore right before the server copies into it, there is Startup Hook callback.

The following example code illustrates how the Startup Hook callback may look like:

/********************************************************************* FUNCTION startup_hook_callback** Startup Hook callback* The Startup Hook Complete function is the* user/system callback that is invoked before* any changes to the <startup> during edit-config, copy-config and* delete-config operation.** Max Callbacks: No limit (except available heap memory)** INPUT:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* source_config == datastore which is being copied* target_config == datastore that is being edited** RETURNS:* status********************************************************************/static status_t startup_hook_callback (ses_cb_t *scb,

rpc_msg_t *msg, cfg_template_t *source_config, cfg_template_t *target_config)

{

(void)scb;(void)msg;(void)source_config;(void)target_config;

log_debug("\n\nEnter startup_hook_callback callback");

/* notify application that the <startup> is being modified */ log_debug("\n <startup> is being modified");

return NO_ERR;

} /* startup_hook_callback */

Version 19.10-12 Page 218

Page 219: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.15 Validate Complete Callback

The Validate Complete function is the user/system callback that is invoked after the Validate Phase has been processed during the <commit> operation.

If the callback fails the status of the failing callback is returned immediately and no further callbacks are made. As a result, the server will abort the commit.

The callback is object independent and module independent which means you don't have to link it to the specific object as itis done for EDIT or GET callbacks.

The callback is intended to allow manipulations with the running and candidate configurations (equivalent to completion of validation phase during <commit>).

NOTE:

The <commit> operation is not available if the default target is set to <running>, if the server is run with active :writable:running capability.

The callback is only called after commit operation for the specific phase has finished not after the validate for the specific module or edit is done.

The following function template definition is used for Validate Complete callback functions:

/* Typedef of the validate_complete callback */typedef status_t

(*agt_cb_validate_complete_t)(ses_cb_t *scb, rpc_msg_t *msg, val_value_t *candidate, val_value_t *running);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_validate_complete

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ candidate == candidate val_value_t for the config database to use

▪ running == running val_value_t for the config database to use

• Outputs: none

• Returns: Status of the callback function execution

Version 19.10-12 Page 219

Page 220: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

• Register: agt_cb_validate_complete_register

• Unregister: agt_cb_validate_complete_unregister

6.15.1 Validate Complete Callback Initialization and Cleanup

The Validate Complete callback is object independent and module independent which means you don't have to link it to the specific object as it is done for EDIT or GET callbacks.

NOTE:

The Validate Complete callback is only called after the commit operation for the Validate phase has finished not after the commit for the specific module or edit is done.

The Validate Complete callback function is hooked into the server with the agt_cb_validate_complete_register function, as described below.

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded. Initialization function with the registration of the Validate Complete callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* register validate complete callback */ res = agt_cb_validate_complete_register(validate_compl_callback); if (res != NO_ERR) { return res; }

...}

agt_cb_validate_complete_register

Parameter Description

cbfn The callback function address. This function will be used for the callback invocation

Version 19.10-12 Page 220

Page 221: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

Now, whenever the Validation Phase is done for the commit operation, the callback function will be called and provide the access to the candidate and running datastores. If there are multiple callbacks registered, all the registered callbacks will be called one after another right after the Validation Phase during the commit operation is done.

The following example code illustrates how the Validate Complete callback can be cleaned up. The callbacks cleanup is getting done during Cleanup Phase.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... /* Unregister Validate Complete callback */

agt_cb_validate_complete_unregister(validate_compl_callback);

...}

agt_cb_validate_complete_unregister

Parameter Description

cbfn The callback function address. This function will be cleaned up

Version 19.10-12 Page 221

Page 222: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.16 Apply Complete Callback

The Apply Complete function is the user/system callback that is invoked after the Apply Phase has been processed during the <commit> operation.

If a callback fails the status of the failing callback is returned immediately and no further callbacks are made. As a result, the server will abort the commit. The callback is object independent and module independent which means you don't have to link it to the specific object as it is done for EDIT or GET callbacks.

The callback is intended to allow manipulations with the running and candidate configurations (equivalent to completion of apply phase during <commit>). The callback is only called after commit operation for the specific phase has finished not after the apply for the specific module or edit is done. The following function template definition is used for Apply Complete callback functions:

/* Typedef of the apply_complete callback */typedef status_t

(*agt_cb_apply_complete_t)(ses_cb_t *scb, rpc_msg_t *msg, val_value_t *candidate, val_value_t *running);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_apply_complete

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ candidate == candidate val_value_t for the config database to use

▪ running == running val_value_t for the config database to use

• Outputs: none

• Returns: Status of the callback function execution

• Register: agt_cb_apply_complete_register

• Unregister: agt_cb_apply_complete_unregister

Version 19.10-12 Page 222

Page 223: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.16.1 Apply Complete Callback Initialization and Cleanup

The Apply Complete callback is object independent and module independent which means you don't have to link it to the specific object as it is done for EDIT or GET callbacks.

NOTE:

The Apply Complete is only called after the commit operation for the Apply Phase has finished not after the commit for the specific module or edit is done.

The Apply Complete callback function is hooked into the server with the agt_cb_apply_complete_register function, as described below.

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded. Initialization function with the registration of the Apply Complete callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ... /* register apply complete callback */ res = agt_cb_apply_complete_register(apply_compl_callback); if (res != NO_ERR) { return res; }

...}

Now, whenever the Apply Phase is done for the commit operation, the callback function will be called and provide the access to the candidate and running datastores. If there are multiple callbacks registered, all the registered callbacks will be called one after another right after the Apply Phase during the commit operation is done.

agt_cb_apply_complete_register

Parameter Description

cbfn The callback function address. This function will be used for the callback invocation

Version 19.10-12 Page 223

Page 224: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The following example code illustrates how the Apply Complete callbacks can be cleaned up. The callback cleanup is getting done during Cleanup Phase.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... /* Unregister Apply Complete callback */ agt_cb_apply_complete_unregister(apply_compl_callback);

...}

agt_cb_apply_complete_unregister

Parameter Description

cbfn The callback function address. This function will be cleaned up

Version 19.10-12 Page 224

Page 225: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.17 Commit Complete Callback

The Commit Complete callback is a user/system callback that is invoked when the <commit> operation completes withouterrors or the internal <replay-config> operation completes without errors.

If a callback fails the status of the failing operation is returned immediately and no further Commit Complete callbacks arecalled. The callback is only called after commit operation for the specific phase has finished not after the commit for the specific module or edit is done.

The following function template definition is used for Commit Complete callback functions:

/* Typedef of the callback */ typedef status_t (*agt_commit_complete_cb_t)(agt_commit_type_t commit_type);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per SIL

• File: agt/agt_commit_complete.h

• Template: agt_commit_complete_cb_t

◦ Inputs:

▪ commit_type == The type of commit that was just completed:

AGT_COMMIT_TYPE_NORMAL: <commit> operation was completed

AGT_COMMIT_TYPE_REPLAY: <replay-commit> operation was completed

• Outputs: none

• Returns: status_t:

Status of the callback function execution

• Register: agt_commit_complete_register

• Unregister: agt_commit_complete_unregister

Version 19.10-12 Page 225

Page 226: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.17.1 Commit Complete Callback Initialization and Cleanup

The Commit Complete callback is object independent and module independent which means you don't have to link it to the specific object as it is done for EDIT or GET callbacks.

NOTE:

The Commit Complete callback is only called after the commit operation for the Commit Phase has finished not after the commit for the specific module or edit is done.

The specific Commit Complete callback function is hooked into the server with the agt_cb_commit_complete_register function, as described below.

extern status_t agt_commit_complete_register (const xmlChar *modname, agt_commit_complete_cb_t cb);

agt_commit_complete_register

Parameter Description

modname Module name of the module registering the callback

cbfn The callback function address. This function will be used for the callback invocation

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function, with the registration of the Commit Complete callback may look as described below. The register function for the Commit Complete callback is slightly different then for other Phases. Note, that it is passing module nameto the registering function, which means that only one active callback per SIL code can be assigned. If you register one callback and then trying to register another for the same module, the first one will be deactivated and the second will become active.

This registered callback function will be called after all changes to the candidate database have been committed. If there aremultiple callbacks registered (for different modules), all the registered callbacks will be called one after another right after the Commit Phase during the commit operation is done. It will be called right after the commit operation is done.

Initialization function with the registration of the specific Commit Complete callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t

Version 19.10-12 Page 226

Page 227: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

interfaces_init (void) { ... /* register commit complete callback */ res = agt_commit_complete_register(EXAMPLE_MODNAME, commit_compl_callback); if (res != NO_ERR) { return res; }

...}

Now, whenever the Commit Phase is done for the commit operation, the callback function will be called.

The following example code illustrates how the Commit Complete callback can be cleaned up. The callback cleanup is getting done during module Cleanup Phase.

extern void agt_commit_complete_unregister (const xmlChar *modname);

agt_commit_complete_unregister

Parameter Description

modname Module name of the module unregistering the callback

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... /* Unregister Commit Complete callback */

agt_commit_complete_unregister(EXAMPLE_MODNAME);

...}

The unregister function for the Commit Complete callback is slightly different then for other Phases. Note, that it is passing module name to the unregistering function.

Version 19.10-12 Page 227

Page 228: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.18 Rollback Complete Callback

The Rollback Complete function is the user/system callback that is invoked after and if the Rollback Phase has been processed during the <commit> operation.

If the callback fails the status of the failing callback is returned immediately and no further callbacks are made. As a result, the server will report an error. The callback is object independent and module independent which means you don't have to link it to the specific object as it is done for EDIT or GET callbacks. The callback is intended to allow manipulations with the running and candidate configurations after the Rollback Phase.

The following function template definition is used for Rollback Complete callback functions:

/* Typedef of the rollback_complete callback */typedef status_t

(*agt_cb_rollback_complete_t)(ses_cb_t *scb, rpc_msg_t *msg,

val_value_t *candidate, val_value_t *running);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt_cb.h

• Template: agt_cb_rollback_complete

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ candidate == candidate val_value_t for the config database to use

▪ running == running val_value_t for the config database to use

• Outputs: none

• Returns: Status of the callback function execution

• Register: agt_cb_rollback_complete_register

• Unregister: agt_cb_rollback_complete_unregister

Version 19.10-12 Page 228

Page 229: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.18.1 Rollback Complete Callback Initialization and Cleanup

The Rollback Complete callback is object independent and module independent which means you don't have to link it to the specific object as it is done for EDIT or GET callbacks.

NOTE:

The Rollback Complete is only called after and if the commit operation for the Rollback Phase has finished not after the commit for the specific module or edit is done.

The Rollback Complete callback function is hooked into the server with the agt_cb_rollback_complete_register function, as described below.

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded. Initialization function with the registration of the Rollback Complete callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ... /* register rollback complete callback */ res = agt_cb_rollback_complete_register(rollback_compl_callback); if (res != NO_ERR) { return res; }

...}

Now, whenever and if the Rollback Phase is done for the commit operation, the callback function will be called and provide the access to the candidate and running datastores. If there are multiple callbacks registered, all the registered callbacks will be called one after another right after the Rollback Phase during the commit operation is done.

agt_cb_rollback_complete_register

Parameter Description

cbfn The callback function address. This function will be used for the callback invocation

Version 19.10-12 Page 229

Page 230: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The following example code illustrates how the Rollback Complete callbacks can be cleaned up. The callback cleanup is getting done during module Cleanup Phase.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... /* Unregister Rollback Complete callback */

agt_cb_rollback_complete_unregister(rollback_compl_callback);

...}

agt_cb_rollback_complete_unregister

Parameter Description

cbfn The callback function address. This function will be cleaned up

Version 19.10-12 Page 230

Page 231: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.19 Commit Completeness Callback Function Example

Let us go through simple examples that will illustrate how to utilize Commit Completeness callbacks.

Consideration:

Consider that there are four modules loaded into the server and each having separate SIL code and you would like to register four different callbacks to be called when validation of respective module is completed on the commit.

When module number one is modified and a commit operation is performed, only callback registered in module one's SIL code should be called. In this way each module owner can write independent callback for his module, without side effects to other module callbacks.

Solution:

The Commit Completeness Callbacks are not regular SIL callbacks, they cannot not be called based on the specific module or object or any other parameter. They can be named as “global” callbacks.

They can only be called after commit operation for the specific phase has finished not after the commit for the specific module or object is done.

The server has no control of identifying what module and when the specific edit is done for the specific module. The edit can be as complex as having multiple modules modifications at the same time. It may reference other modules as a leafref or augment, and those modules can also be triggered during the same edit.

If keep in mind that before you execute the commit operation it is allowed to modify candidate datastore as many times as needed. E.g: edit on the first module's node, then edit on the second module's node, then again edit on node from the first module, etc. Then it would be almost impossible to tell when the Validation Complete callback should be triggered for a particular module. Only if the server would sort edits based on module which will significantly affect performance or limit number of edits at the same time to one, which is not possible.

In the considering scenario with four SIL codes for four different modules you don't have to register four Commit Completeness callbacks for each module. You may register just one callback for each corresponding phase that will take care of the commit operation.

If you want to have a callback that will be invoked when a specific module or object is getting modified, then you should consider regular EDIT callbacks, that described in the section named “Main Transaction Callback Examples”.

The following example code illustrates how the Validate Complete callback may look like.

/******************************************************************** * FUNCTION validate_compl_callback* * Validate Complete callback * * Max Callbacks: No limit (except available heap memory)* * INPUTS: * scb == session control block making the request * msg == incoming rpc_msg_t in progress * candidate == candidate val_value_t for the config database to use * running == running val_value_t for the config database to use * * RETURNS: * status ********************************************************************/

Version 19.10-12 Page 231

Page 232: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

static status_t validate_compl_callback (ses_cb_t *scb,

rpc_msg_t *msg, val_value_t *candidate, val_value_t *running)

{ (void)scb; (void)msg; (void)candidate; (void)running;

/* notify application that the Validate phase is done */

/* validate candidate */

/* validate running */

return res;

} /* validate_compl_callback */

Assuming there are multiple modules loaded and many modules are modified. Now, when a commit command triggers the Validate Complete Callback and it is getting invoked it means that all validations for all the modules and all edits are completed at this point. Similarly appropriate callbacks are called for all phases - when commit operation for that phase is finished for all modules and edits.

In order to efficiently detect if configurations have changed, there are multiple compare APIs that compares configuration of running and candidate datastores. To detect if the configurations for specific module has changed there is no very efficient way. However, it is possible, but will require couple loops that will have to loop through the whole running config and check every node for changes against candidate config.

For this scenario, it would be better to register Transaction Hook callback for a specific node(s) in the specific module. In this case you will have direct access to the node that is changing.

The following example code illustrates how the Apply Complete callback may look like.

/******************************************************************** * FUNCTION apply_compl_callback* * Apply Complete callback * * Max Callbacks: No limit (except available heap memory)* * INPUTS: * scb == session control block making the request * msg == incoming rpc_msg_t in progress * candidate == candidate val_value_t for the config database to use * running == running val_value_t for the config database to use * * RETURNS: * status ********************************************************************/ static status_t apply_compl_callback (ses_cb_t *scb,

rpc_msg_t *msg, val_value_t *candidate,val_value_t *running)

Version 19.10-12 Page 232

Page 233: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

{ (void)scb; (void)msg; (void)candidate; (void)running;

/* notify application that the Apply phase is done */

/* process configs here */

return res;

} /* apply_compl_callback */

The following example code illustrates how the Commit Complete callback may look like.

/******************************************************************** * FUNCTION commit_compl_callback* * Commit Complete callback * * INPUTS:* commit_type == enum identifying commit type (normal or replay)* * RETURNS: * status ********************************************************************/ static status_t commit_compl_callback (agt_commit_type_t commit_type){ (void)commit_type;

/* notify application that the Commit phase is done */

return res;

} /* apply_compl_callback */

Version 19.10-12 Page 233

Page 234: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.20 Dynamic Default Hook Callback

The Dynamic Default Hook function is the user/system callback that can be used to set up dynamic default value to the non-default leafy nodes during load or edit-config operations. It is invoked when the server checks if the node has any defaults and if there is no any YANG defined defaults the server can update the node with custom “system” default value.

NOTE:

The Dynamic Default Hook callback is NOT to overwrite a YANG default value, it is only for the nodes that do not have adefault statement defined. The YANG default values can only be changed statically with help of deviations. The Dynamic Default Hook callback should be used to dynamically change a value of the node. This callback will NOT make the value of the leaf or leaf-list to be default value as if YANG default statement sets it.

If the callback fails and return an error the transaction will be terminated and the server will generate an error. However, theERR_NCX_SKIPPED or ERR_NCX_NO_INSTANCE status will cause the serve to skip over the callback node and do not terminate the transaction.

The Dynamic Default Hook callbacks will be invoked during the following operations:

• Load startup configuration: the server will try to add defaults for all the nodes in the startup configuration and in addition will try to invoke Dynamic Default Hook callbacks to set up custom dynamic default nodes if any;

• EDIT configurations: the server will try to add defaults for all the nodes in the <edit-config> and in addition will try to invoke Dynamic Default Hook callbacks to set up custom dynamic default nodes if any.

The Dynamic Default Hook callbacks specifications and limitations:

• Allowed only for leaf or leaf-list nodes;• Not allowed for keys nodes;• Not allowed for RPC/ACTION input nodes;• Not invoked on deletion of any nodes;• No support for yangdump-pro auto-generated code;• No support for SIL-SA;• Only one dynamic default value is allowed for leaf-list nodes.

Version 19.10-12 Page 234

Page 235: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The following function template definition is used for Dynamic Default Hook callback functions:

/********************************************************************* Typedef of the ncx_def_hook_cbfn_t callback** The Dynamic Default Hook function is the user/system callback* that is invoked before the server checks if the node has* any defaults and if there is not any YANG defined defaults* the server can update the node with custom "system" default* value.** Run an instrumentation-defined function* for val set default event** INPUTS:* parentval == parent val_value node to use* obj == object template to use** OUTPUTS* *buff == malloced buffer that represents a new default value** RETURNS:* status: ERR_NCX_SKIPPED or ERR_NCX_NO_INSTANCE will cause the server* to skip over this node. Otherwise the server will report an* error and ternimate the transaction**********************************************************************/typedef status_t (*ncx_def_hook_cbfn_t) (struct val_value_t_ *parentval, struct obj_template_t_ *obj, xmlChar **buff);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per object

• File: ncxtypes.h

• Template: ncx_def_hook_cbfn_t

◦ Inputs:

▪ parentval == parent val_value node to use

▪ obj == object template to use

◦ Outputs:

▪ *buff == malloced buffer that represents a new default value

• Returns: status:

◦ ERR_NCX_SKIPPED or ERR_NCX_NO_INSTANCE will cause the server to skip over this node.

◦ Otherwise the server will report an error and terminate the transaction

• Register: agt_cb_def_hook_register

• Unregister: agt_cb_def_hook_unregister

Version 19.10-12 Page 235

Page 236: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.20.1 Dynamic Default Hook Callback Initialization and Cleanup

The Dynamic Default Hook callback function is hooked into the server with the agt_cb_order_hook_register function, described below:

/********************************************************************* FUNCTION agt_cb_def_hook_register** Register an object specific Dynamic Default callback function* to enable custom default value setup for a specified node** INPUTS:* defpath == XPath with default (or no) prefixes* defining the object that will get the callbacks* cbfn == address of callback function to use for* Dynamic Default callbacks** RETURNS:* status*********************************************************************/extern status_t agt_cb_def_hook_register (const xmlChar *defpath, ncx_def_hook_cbfn_t cbfn);

The register function is used to declare a specific callback function for Dynamic Default Hook callbacks. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the registration of the Dynamic Default Hook callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* Register a Dynamic Default Hook callback. */ res = agt_cb_def_hook_register((const xmlChar *)"/interfaces/interface/type", default_hook_callback); if (res != NO_ERR) { return res; }

...}

Version 19.10-12 Page 236

Page 237: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The following example code illustrates how the callback can be cleaned up. The callback cleanup is getting done during module Cleanup Phase.

/********************************************************************* FUNCTION agt_cb_def_hook_unregister** Unregister Dynamic Default callback functions for a specific object** INPUTS:* defpath == definition XPath location** RETURNS:* none*********************************************************************/extern void agt_cb_def_hook_unregister (const xmlChar *defpath);

The callback cleanup function of the Dynamic Default Hook may look as follows:

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ...

/* Unregister a Dynamic Default Hook callback */ agt_cb_def_hook_unregister((const xmlChar *)"/interfaces/interface/type");

...}

Version 19.10-12 Page 237

Page 238: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

6.20.2 Dynamic Default Hook Callback Function Examples

The following sections illustrates how to utilize the Dynamic Default Hook callback in examples.

NOTE:

The Dynamic Default Hook callback is not part of the auto-generated code and you will have to add a registration, clean up and callback function to a desired node that you want to become a Dynamic node.

In this example we are going to register callbacks for multiple leafy nodes in order to make them dynamic nodes. Specifically, we are going to register callback for "type" leaf, so any time a new "interface" is getting loaded or created the server will be able to dynamically update the "type" leaf in that interface based on the "name" value. Refer to the attached YANG module and its SIL code for a complete example.

As an example callback function refer to the following snippet. In this example, if the "name" of the "interface", during the create or load operation, is "vlan" or "lag" then the callback will set the dynamic value to return to the server. The server will use this value to set the "type" value in the same transaction dynamically.

/********************************************************************* FUNCTION default_hook_callback** The Dynamic Default Hook function is the user/system callback* that is invoked before the server checks if the node has* any defaults and if there is not any YANG defined defaults* the server can update the node with custom "system" default* value.** Run an instrumentation-defined function* for val set default event** INPUTS:* parentval == parent val_value node to use* obj == object template to use** OUTPUTS* *buff == malloced buffer that represents a new default value** RETURNS:* status: ERR_NCX_SKIPPED or ERR_NCX_NO_INSTANCE will cause the server* to skip over this node. Otherwise the server will report an* error and ternimate the transaction**********************************************************************/static status_t default_hook_callback (val_value_t *parentval, obj_template_t *obj, xmlChar **buff){ status_t res = NO_ERR;

if (LOGDEBUG) { log_debug("\n\nEnter Dynamic Default Hook callback for '%s'", obj_get_name(obj)); }

Version 19.10-12 Page 238

Page 239: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* Check the key value of the parent list to setup the * Dynamic leaf accordingly */ val_value_t *child_val = NULL; if (parentval) { child_val = val_find_child(parentval, DEF_HOOK_TEST_MOD, (const xmlChar *)"name"); }

const xmlChar *defval = NULL; if (child_val && !xml_strcmp(obj_get_name(obj), (const xmlChar *)"type")) { if (LOGDEBUG) { log_debug("\nCurrent list key value:'%s'", VAL_STR(child_val)); }

if (!xml_strncmp(VAL_STR(child_val), (const xmlChar *)"vlan", 4)) {

/* check if the interface key value is starting with 'vlan' */ defval = (const xmlChar *)"vlan"; } else if (!xml_strncmp(VAL_STR(child_val), (const xmlChar *)"lag", 3)) {

/* check if the interface key value is starting with 'lag' */ defval = (const xmlChar *)"lag"; } else {

/* otherwise just skip over this node */ return ERR_NCX_NO_INSTANCE; } } else { if (typ_is_string(obj_get_basetype(obj))) { defval = (const xmlChar *)"NON-DEF-STR"; } else { defval = (const xmlChar *)"non-def-enum"; } }

if (LOGDEBUG) { log_debug("\nDynamic Default value set to:'%s'", defval); }

/* Malloc a buffer that will be used to set the default value */ *buff = xml_strdup(defval); if (*buff == NULL) { return ERR_NCX_SKIPPED; }

return res;

} /* default_hook_callback */

Version 19.10-12 Page 239

Page 240: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7 System CallbacksThe callback functions described in this section are invoked as part of a normal server operation.

They can be registered from the yp-system library module or a SIL module. Some internal functions are documented as well. These are needed by the system and multiple callbacks are not supported.

Refer to the file /usr/share/yumapro/src/libsystem/src/example-system.c for examples of the callbacks in this section.

API Description

Candidate Reload callback cfg_reload_candidate_cb_t: There can be one callback registered to beinvoked each time the candidate datastore is reloaded from the runningdatastore, such as the <discard-changes> operation.

Module Load callback ncx_load_cbfn_t: There can be multiple callbacks registered to be invokedwhen a module is loaded into the server. A transaction to set moduledefaults will also be generated, in addition to this callback.

Module Unload callback ncx_unload_cbfn_t: There can be multiple callbacks registered to beinvoked when a module is unloaded from the server. A transaction toremove module configuration data will also be generated, in addition to thiscallback.

Configuration Replay Start or Finish callback

agt_replay_fn_t: There can be one callback registered that is called at thestart and again at the end of a configuration replay transaction.

NV-Load callback agt_nvload_fn_t: There can be one callback registered that is invoked whenthe server needs to retrieve the configuration contents from non-volatilestorage.

NV-Save callback agt_nvsave_fn_t: There can be one callback registered that is invoked whenwhen some config needs to be saved to Non-Volatile storage.

Config Replay callback agt_replay_fn_t: The callback is invoked when a configuration replay isstarted or finished.

Periodic Timer Service agt_timer_fn_t: The timer callback function is expected to do a short amount of work, and not block the running process. The function returns zero for a normal exit, and -1 if there was an error and the timer should be destroyed.

Version 19.10-12 Page 240

Page 241: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.1 Candidate Reload Callback

The Candidate Reload callback is an internal system callback that is used to clear some cached validation data when the running configuration is loaded into to candidate datastore.

The following function template definition is used for Candidate Reload callback functions:

/* Typedef of the callback */ typedef void (*cfg_reload_candidate_cb_t) (void);

Callback Template

• Type: Internal use only

• Max Callbacks: 1

• File: ncx/cfg.h

• Template: cfg_reload_candidate_cb_t

◦ Inputs: none

◦ Outputs: none

◦ Returns: none

• Register: cfg_register_reload_candidate_cb

• Unregister: none

Version 19.10-12 Page 241

Page 242: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.1.1 Candidate Reload Callback Example

There can be one callback registered to be invoked each time the candidate datastore is reloaded from the running datastore,such as the <discard-changes> operation. Or anytime the candidate is filled in from <startup>, <running>, or in line.

If the server is run with active :writable-running capability the callback will not be available since the candidate configuration datastore is not available when the capability is active.

The cfg_register_reload_candidate_cb function is used to declare the callback. The registration is done during the Initialization Phase 2 after the running configuration has been loaded from the startup file.

extern void cfg_register_reload_candidate_cb (cfg_reload_candidate_cb_t cbfn);

Initialization function with the Candidate Reload callback registration may look as follows:

/******************************************************************** * FUNCTION do_init2* * Call the Post Running Config Set Initialization Functions* *********************************************************************/ static status_t do_init2 (boolean startup_loaded){ ...

/* initialize the reload_candidate callback function */ cfg_register_reload_candidate_cb(agt_val_clean_cached_results);

...}

Version 19.10-12 Page 242

Page 243: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.2 Module Load Callback

The Module Load callback is a user/system callback that is invoked when a YANG module is loaded into the server. This callback is only invoked for main modules, not submodules.

The following function template definition is used for Module Load callback functions:

/* Typedef of the callback */ typedef void (*ncx_load_cbfn_t) (ncx_module_t *mod);

Callback Template

• Type: Internal and User Callback

• Max Callbacks: NCX_MAX_LOAD_CALLBACKS (8: ncx/ncxconst.h)

• File: ncx/ncx.h

• Template: ncx_load_cbfn_t (ncx/ncxtypes.h)

◦ Inputs:

▪ mod == the internal module structure for the module that was just loaded

◦ Outputs: none

◦ Returns: none

• Register: ncx_set_load_callback

• Unregister: ncx_clear_load_callback

Where, MOD pointer represents a module control block structure that is defined in the netconf/src/ncx/ncxtypes.h. This control block is a representation of one module or submodule during and after parsing. It provides access to the module specific information, such as module name, revision, prefix, and other module specific information. Note, all the fields in this structure should NOT be changed and if accessed, should NOT be accessed directly. This control block ideally should be used only for getting more information about the loaded module, not for alteration of any of its fields.

Version 19.10-12 Page 243

Page 244: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.2.1 Module Load Callback Initialization and Cleanup

The ncx_set_load_callback function is used to declare the Module Load callback. The registration can be done during the Initialization Phase 2 after the running configuration has been loaded from the startup file.

extern status_t ncx_set_load_callback (ncx_load_cbfn_t cbfn);

Initialization function with the Module Load callback registration may look as follows:

/******************************************************************** * FUNCTION interfaces_init2* * initialize the server instrumentation library.* Initialization Phase 2* *********************************************************************/ static status_t interfaces_init2 (void) { ...

/* register load module callback */ res = ncx_set_load_callback(add_module_callback); if (res != NO_ERR) { return res; }

...}

The following example code illustrates how the Module Load callback can be cleaned up. The callbacks cleanup is getting done during module Cleanup Phase.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... ncx_clear_load_callback(add_module_callback);

...}

Version 19.10-12 Page 244

Page 245: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.2.2 Module Load Callback Function Example

Let us go through simple examples that will illustrate how to utilize the Module Load callbacks. In this example, the callback code will generate val_value_tree that will represent a new just loaded module and will add it to the static (config=false) node any time a new module is loaded to the server. In this example we are going to use “ietf-yang-library” YANG data model.

The following example code illustrates how the Module Load callback may look like.

static val_value_t *mymodules_val;

/******************************************************************** * FUNCTION add_module_callback * * Run an instrumentation-defined function * for a 'module-loaded' event * * INPUTS: * mod == module that was added to the registry * ********************************************************************/ static void add_module_callback (ncx_module_t *mod) { status_t res = NO_ERR;

val_value_t *module = make_module_val(mod, mymodule_obj, &res); if (module == NULL) { log_error("\nError: could not make val_value_t for module"); } else { res = val_child_add(module, mymodules_val); if (res != NO_ERR) { val_free_value(module); } }

} /* add_module_callback */

In the following part of the above code example we are constructing a val_value tree based on the ncx_module_t information provided by the Module Load event. Any time a new module is loaded into the server, this callback function will be called with MOD pointer, that contains the complete information about just loaded module. Based on this information, this callback function will construct the static data.

...

val_value_t *module = make_module_val(mod, mymodule_obj, &res);

...

Version 19.10-12 Page 245

Page 246: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The following functions may be used to obtain required information from the loaded module:

• ncx_get_modname() - Get the main module name

• ncx_get_mod_nsid() - Get the main module namespace ID

• ncx_get_modversion() - Get the module version

• ncx_get_modnamespace() - Get the module namespace URI

The make_module_val function constructs a static data based on the module information. After a val_value tree for the module is constructed, the module value is added to the mymodules_val parent.

The mymodules_val pointer represents a parent of the module list, which is a container “modules”.

/******************************************************************** * FUNCTION make_module_val * * make a val_value_t struct for a 'mod' module * * Path: /modules/module * * RETURNS: * error status ********************************************************************/ static val_value_t * make_module_val (ncx_module_t *mod, obj_template_t *module_obj, status_t *res){ *res = NO_ERR;

/* create /module node */ val_value_t *module_val = val_new_value(); if (!module_val) { *res = ERR_INTERNAL_MEM; return NULL; } val_init_from_template(module_val, module_obj);

/* create list key /module/name */ val_value_t *childval = agt_make_leaf(module_obj, (const xmlChar *)"name", ncx_get_modname(mod), res); if (!childval) { val_free_value(module_val); return NULL; } *res = val_child_add(childval, module_val); if (*res != NO_ERR) { val_free_value(childval); val_free_value(module_val); return NULL; }

/* create list key module/revision */

Version 19.10-12 Page 246

Page 247: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

childval = agt_make_leaf(module_obj, (const xmlChar *)"revision", ncx_get_modversion(mod), res); if (!childval) { val_free_value(module_val); return NULL; } *res = val_child_add(childval, module_val); if (*res != NO_ERR) { val_free_value(childval); val_free_value(module_val); return NULL; }

/* generate the internal index Q chain */ *res = val_gen_index_chain(module_obj, module_val); if (*res != NO_ERR) { log_error("\nError: could not generate index chain (%s)", get_error_string(*res)); val_free_value(module_val); return NULL; }

return module_val;

} /* add_module_callback */

In the above code example, we constructed a list entry with two leafs - “name” and “revision” based on the loaded module information. Make sure to generate index chain after you construct a list entry to let the server to normalize and populate list indexes.

...

val_value_t *module = make_module_val(mod, mymodule_obj, &res); if (module == NULL) { log_error("\nError: could not make val_value_t for module"); } else { res = val_child_add(module, mymodules_val); if (res != NO_ERR) { val_free_value(module); } }

...

To summarize, after we created the list entry based on the loaded module information and generated the index chain, we canadd this list entry to the parent container mymodules_val with help of val_child_add function.

Version 19.10-12 Page 247

Page 248: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.3 Module Unload Callback

The Module Unload callback is a user/system callback that is invoked when a YANG module is unloaded from the server. This callback is only invoked for main modules, not submodules.

The following function template definition is used for Module Unload callback functions:

/* Typedef of the callback */ typedef void (*ncx_unload_cbfn_t) (ncx_module_t *mod);

Callback Template

• Type: Internal and User Callback

• Max Callbacks: NCX_MAX_LOAD_CALLBACKS (8: ncx/ncxconst.h)

• File: ncx/ncx.h

• Template: ncx_unload_cbfn_t (ncx/ncxtypes.h)

◦ Inputs:

▪ mod == the internal module structure for the module that is being unloaded

◦ Outputs: none

◦ Returns: none

• Register: ncx_set_unload_callback

• Unregister: ncx_clear_unload_callback

Where, MOD pointer represents a module control block structure that is defined in the netconf/src/ncx/ncxtypes.h. This control block is a representation of one module or submodule during and after parsing. It provides access to the module specific information, such as module name, revision, prefix, and other module specific information. Note, all the fields in this structure should NOT be changed and if accessed, should NOT be accessed directly. This control block ideally should be used only for getting more information about the unloaded module, not for alteration of any of its fields.

Version 19.10-12 Page 248

Page 249: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.3.1 Module Unload Callback Initialization and Cleanup

The ncx_set_unload_callback function is used to declare the Module Unload callback. The registration can be done during the Initialization Phase 2 after the running configuration has been loaded from the startup file.

Initialization function with the Module Unload callback registration may look as follows:

/******************************************************************** * FUNCTION interfaces_init2* * initialize the server instrumentation library.* Initialization Phase 2* *********************************************************************/ static status_t interfaces_init2 (void) { ...

/* register unload module callback */ res = ncx_set_unload_callback(remove_module_callback); if (res != NO_ERR) { return res; }

...}

The following example code illustrates how the Module Unload callback can be cleaned up. The callbacks cleanup is getting done during module Cleanup Phase.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ... ncx_clear_unload_callback(remove_module_callback);

...}

Version 19.10-12 Page 249

Page 250: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.3.2 Module Unload Callback Function Example

Let us go through simple examples that will illustrate how to utilize the Module Unload callbacks. In this example, the callback code will find a val_value tree, based on the information from MOD pointer, find a tree and remove it from the static data list. In this example we are still using the same “ietf-yang-library” YANG data model.

The following example code illustrates how the Module Unload callback may look like.

/******************************************************************** * FUNCTION remove_module_callback * * Run an instrumentation-defined function * for a 'module-unload' event * * INPUTS: * mod == module that was added to the registry * ********************************************************************/ static void remove_module_callback (ncx_module_t *mod) { remove_module(mod);

} /* add_module_callback */

In the remove_module() function we are removing a val_value tree based on the ncx_module_t information provided by the Module Load event. Any time a new module is unloaded from the server, this callback function will be called with MOD pointer, that contains the complete information about just unloaded module. Based on this information, this callback function will find and remove the static data associated with this module.

/******************************************************************** * FUNCTION remove_module * * Remove a module entry from the static modules list* * INPUTS: * mod == module to remove * ********************************************************************/ static void remove_module (ncx_module_t *mod) {

xmlns_id_t nsid = val_get_nsid(mymodules_val); val_value_t *module = val_get_first_child(mymodules_val); for (; module; module = val_get_next_child(module)) {

val_value_t *checkval = val_find_child_fast(module, nsid, (const xmlChar *)"name");

/* check the module name, if it match, remove the module from the list */ if (checkval) {

Version 19.10-12 Page 250

Page 251: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

if (xml_strcmp(VAL_STR(checkval), ncx_get_modname(mod))) { continue; } } else { continue; // error }

/* check the module revision, if it match, remove the module from the list */ if (ncx_get_modversion(mod)) { checkval = val_find_child_fast(module, nsid, (const xmlChar *)"revision"); if (checkval) { if (xml_strcmp(VAL_STR(checkval), ncx_get_modversion(mod))) { continue; } } else { continue; // error! } }

val_remove_child(module); val_free_value(module); return; } } /* remove_module */

The following functions may be used to obtain required information from the unloaded module:

• ncx_get_modname() - Get the main module name

• ncx_get_mod_nsid() - Get the main module namespace ID

• ncx_get_modversion() - Get the module version

• ncx_get_modnamespace() - Get the module namespace URI

The mymodules_val pointer represents a parent of the module list.

The following code illustrates how to loop through the mymodules_val parent in order to retrieve all the children – modules.

...

val_value_t *module = val_get_first_child(mymodules_val); for (; module; module = val_get_next_child(module)) {

}

...

Once we got a module list entry pointer, we can try to match its child (module name) with a module name of the unloaded module in order to proceed to the removal. The following code demonstrates how to validate the module name:

Version 19.10-12 Page 251

Page 252: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

...

val_value_t *checkval = val_find_child_fast(module, nsid, (const xmlChar *)"name");

/* check the module name, if it match, remove the module from the list */ if (checkval) { if (xml_strcmp(VAL_STR(checkval), ncx_get_modname(mod))) { continue; } } else { continue; // error }

...

If the module name matched already, we will try to match and the revision date. The revision statement is optional for the module, so we need to make sure that the module actually has the revision statement prior the revision match test. The following code demonstrates how to validate the module revision date:

...

/* check the module revision, if it match, remove the module from the list */ if (ncx_get_modversion(mod)) { checkval = val_find_child_fast(module, nsid, (const xmlChar *)"revision"); if (checkval) { if (xml_strcmp(VAL_STR(checkval), ncx_get_modversion(mod))) { continue; } } else { continue; // error! } }

...

After we verify that the unloaded module is in the list, we will remove it from the list:

...

val_remove_child(module); val_free_value(module);

...

The val_remove_child function removes the child value node from its parent value node, from its parent mymodules_val.

The it is freed with val_free_value.

Version 19.10-12 Page 252

Page 253: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.4 NV-Load Callback

The NV-Load callback function is a user callback that is invoked when the running configuration needs to be read from non-volatile storage. A configuration filespec is passed to this callback that contains the configuration that needs to be saved to non-volatile storage.

The following function template definition is used for NV-Load callback functions:

/* Typedef of the callback */ typedef status_t

(*agt_nvload_fn_t) (ncx_display_mode_t *encoding,xmlChar **filespec);

Callback Template

• Type: User Callback

• Max Callbacks: 1

• File: agt/agt.h

• Template: agt_nvload_fn_t

◦ Inputs:

▪ encoding == the address of the return encoding used in the config file: (values other than XML are TBD)

▪ filespec == the address of the return filespec of the configuration loaded from non-volatile storage

◦ Outputs:

▪ Encoding == set to the encoding used in the config file: (values other than XML are TBD)

▪ Filespec == set to a malloced string containing the filespec of the configuration loaded from non-volatile storage. This must be freed by the called if non-NULL.

Set to NULL if an error returned

Set to NULL if NO_ERR returned to indicate that the factory config is being loaded

• Returns: status_t:

Status of the callback function execution

• Register: agt_register_local_nv_handler

• Unregister: none

Version 19.10-12 Page 253

Page 254: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.4.1 NV-Load Callback Initialization and Cleanup

The agt_register_local_nv_handler function is used to declare the NV-Load callback. The registration can be done duringthe Initialization Phase 2, after the running configuration has been loaded from the startup file.

extern status_t agt_register_local_nv_handler (agt_nvload_fn_t load_fn, agt_nvsave_fn_t store_fn);

Initialization function with the NV-Load callback registration may look as follows:

#define EXAMPLECONFIG_SPEC (const xmlChar *)"/tmp/example-config.xml"

/******************************************************************** * FUNCTION interfaces_init2* * initialize the server instrumentation library.* Initialization Phase 2* *********************************************************************/ static status_t interfaces_init2 (void) { ...

/* register NV-storage handler to load/save config * uncomment following to enable */ res = agt_register_local_nv_handler(nvload_callback, nvsave_callback); if (res != NO_ERR) { return res; }

...}

There is no cleanup function for this callback. The cleanup will be done automatically by the server.

Version 19.10-12 Page 254

Page 255: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.4.2 NV-Load Callback Function Example

The following example code illustrates how the NV-Load callback may look like.

/******************************************************************** * FUNCTION nvload_callback ** this callback is invoked when some config needs to be read * from non-volatile storage * * INPUTS: * encoding == address of encoding for the config * filespec == address of filespec containing the config that was loaded * * OUTPUTS: * *encoding == set to the enum for the encoding used in the config * *filespec == malloced filespec containing the config that was loaded * * RETURNS: * status; error indicates NV-load failed somehow * If return NO_ERR and *filespec == NULL then use the factory config **********************************************************************/ static status_t nvload_callback (ncx_display_mode_t *encoding, xmlChar **filespec) { log_debug("\nEnter nvload_callback ");

*filespec = NULL; *encoding = NCX_DISPLAY_MODE_XML;

status_t res = NO_ERR;

if (ncxmod_test_filespec(EXAMPLE_CONFIG_SPEC)) {

/* file exists so copy the filespec */ *filespec = xml_strdup(EXAMPLE_CONFIG_SPEC); if (*filespec == NULL) { res = ERR_INTERNAL_MEM; } }

return res;

} /* nvload_callback */

Now, when some configuration needs to be read from Non-Volatile storage this callback function will try to find a file specification and copy it into the buffer.

NOTE:

If the callback returns NO_ERR and *filespec is empty then use the factory configuration.

Only XML encoding is supported. The server will save the configuration only in XML.

Version 19.10-12 Page 255

Page 256: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.5 NV-Save Callback

The NV-Save callback function is a user callback that is invoked when the running configuration needs to be saved to non-volatile storage. A configuration filespec is passed to this callback that contains the configuration that needs to be saved to non-volatile storage.

The following function template definition is used for NV-Save callback functions:

/* Typedef of the callback */ typedef status_t

(*agt_nvsave_fn_t) (ncx_display_mode_t encoding,const xmlChar *filespec);

Callback Template

• Type: User Callback

• Max Callbacks: 1

• File: agt/agt.h

• Template: agt_nvload_fn_t

◦ Inputs:

▪ Encoding == the encoding used in the config file: (values other than XML are TBD)

▪ Filespec == the filespec of the configuration to save to non-volatile storage

◦ Outputs: none

◦ Returns: status_t:

Status of the callback function execution

• Register: agt_register_local_nv_handler

• Unregister: none

Version 19.10-12 Page 256

Page 257: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.5.1 NV-Save Callback Initialization and Cleanup

The agt_register_local_nv_handler function is used to declare the NV-Save callback. The registration can be done during the Initialization Phase 2, after the running configuration has been loaded from the startup file.

Initialization function with the NV- Save callback registration may look as follows:

#define EXAMPLECONFIG_SPEC (const xmlChar *)"/tmp/example-config.xml"

/******************************************************************** * FUNCTION interfaces_init2* * initialize the server instrumentation library.* Initialization Phase 2* *********************************************************************/ static status_t interfaces_init2 (void) { ...

/* register NV-storage handler to load/save config * uncomment following to enable */ res = agt_register_local_nv_handler(nvload_callback, nvsave_callback); if (res != NO_ERR) { return res; }

...}

There is no cleanup function for this callback. The cleanup will be done automatically by the server.

Version 19.10-12 Page 257

Page 258: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.5.2 NV-Save Callback Function Example

The following example code illustrates how the NV-Save callback may look like.

/******************************************************************** * FUNCTION nvsave_callback ** this callback is invoked when some config needs to be saved * to non-volatile storage * * INPUTS: * encoding == encoding format for the config (xml only allowed value) * filespec == filespec containing the config to save * RETURNS: * status; error indicates NV-save failed somehow **********************************************************************/ static status_t example_nvsave (ncx_display_mode_t encoding, const xmlChar *filespec) { status_t res = NO_ERR;

if (filespec == NULL || *filespec == 0) { res = ERR_NCX_INVALID_VALUE; } else if (encoding != NCX_DISPLAY_MODE_XML) { res = ERR_NCX_INVALID_VALUE; } else { res = ncxmod_copy_text_file(filespec, EXAMPLE_CONFIG_SPEC); }

return res;} /* nvsave_callback */

Now, when some configuration needs to be saved to Non-Volatile storage this callback function will try to save specified configuration into specific Non-Volatile storage.

Version 19.10-12 Page 258

Page 259: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.6 Session Hook Callback

The Session Hook callback function is a user callback that is invoked when a session starts and ends.

This callback is invoked before any data structures and components have been cleaned up and their data destroyed. It can beused to perform session end or start tasks that are not related to a specific YANG module.

The following function template definition is used for Session Hook callback functions:

/* Typedef of the agt_cb_session_hook_t callback** The Session Hook callback is invoked when a session starts* and ends.* Use ses.h macros like SES_MY_USERNAME(scb) to get* data like client username.* Max Callbacks: No limit (except available heap memory)** INPUTS:* ses_event == session event type* scb == session control block for the session event** OUTPUTS:* none** RETURNS:* none*/typedef void (*agt_cb_session_hook_t) (ncx_ses_event_t ses_event, const ses_cb_t *scb);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt/agt_cb.h

• Template: agt_cb_session_hook_t

◦ Inputs:

▪ ses_event == session event type

• NCX_SES_EVENT_START

• NCX_SES_EVENT_END

▪ scb == session control block

◦ Outputs: none

◦ Returns: none

• Register: agt_cb_session_hook_register

• Unregister: agt_cb_session_hook_unregister

Version 19.10-12 Page 259

Page 260: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.6.1 Session Hook Callback Initialization and Cleanup

The agt_cb_session_hook_register function is used to declare the Session Hook callback. The registration can be done during the Initialization Phase, before or after the running configuration has been loaded from the startup file.

Initialization function with the Session Hook callback registration may look as follows:

status_t y_yumaworks_server_init (const xmlChar *modname, const xmlChar *revision){ status_t res = NO_ERR;

// ... load module, etc.

/* Register a Session Hook callback */ res = agt_cb_session_hook_register(session_hook_callback);

return res;}

The following example code illustrates how the Session Hook callback can be cleaned up. The callback cleanup is getting done during module Cleanup Phase.

void y_yumaworks_server_cleanup (void){ ...

/* Unregister a Session Hook callback. */ agt_cb_session_hook_unregister(session_hook_callback);

...}

Version 19.10-12 Page 260

Page 261: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.6.2 Session Hook Callback Function Example

In the following example we are going to register Session Hook callbacks. In the callback function we are going to check ifa session that is getting started is a RESTCONF session and the input encoding is XML and then will generate specific logging information for the current session. Refer to the attached YANG module and its SIL code for a complete example.

/********************************************************************* FUNCTION session_hook_callback** The Session Hook callback is invoked when a session starts* and ends.** INPUTS:* ses_event == session event type* scb == session control block for the session event** RETURNS:* status********************************************************************/static void session_hook_callback (ncx_ses_event_t ses_event, const ses_cb_t *scb){ if (LOGDEBUG) { log_debug("\n\nEnter Session Hook callback for %s@%s", SES_MY_USERNAME(scb) ? SES_MY_USERNAME(scb) : NCX_EL_NOBODY, SES_PEERADDR(scb) ? SES_PEERADDR(scb) : NCX_EL_LOCALHOST); }

/* Perform specific tasks when the session is ended or started * and only if the current session protocol is RESTCONF * and the session has an input that is encoded in XML */ ncx_display_mode_t input_mode = SES_IN_ENCODING(scb); if (input_mode == NCX_DISPLAY_MODE_XML) {

if (SES_PROTOCOL(scb) == NCX_PROTO_RESTCONF) { if (ses_event == NCX_SES_EVENT_START) {

if (LOGDEBUG) { log_debug("\n ++++ Session Start ++++"); } } else if (ses_event == NCX_SES_EVENT_END) {

if (LOGDEBUG) { log_debug("\n ---- Session END ----"); } } } }

return;

} /* session_hook_callback */

Version 19.10-12 Page 261

Page 262: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.7 Shutdown Callback

The Shutdown callback function is a user callback that is invoked when the server is about to restart or shutdown.

This callback is invoked before any data structures and components have been cleaned up and their data destroyed. It can beused to perform on-exit tasks that are not related to a specific YANG module.

The following function template definition is used for Shutdown callback functions:

/* Typedef of the agt_shutdown_cb_t callback** The Shutdown callback is the user/system callback* that is invoked at the start of a normal agt_cleanup* A normal shutdown or restart is in progress. This callback* is not invoked if the server crashes.** Max Callbacks: No limit (except available heap memory)** INPUTS:* none** OUTPUTS:* none** RETURNS:* none*/typedef void (*agt_cb_shutdown_t) (void);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt/agt_cb.h

• Template: agt_cb_shutdown_t

◦ Inputs: none

◦ Outputs: none

◦ Returns: none

• Register: agt_cb_shutdown_register

• Unregister: none

Version 19.10-12 Page 262

Page 263: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.7.1 Shutdown Callback Initialization and Cleanup

The agt_cb_shutdown_register function is used to declare the Shutdown callback. The registration can be done during the Initialization Phase 2, before or after the running configuration has been loaded from the startup file.

Initialization function with the Shutdown callback registration may look as follows:

status_t y_yumaworks_server_init ( const xmlChar *modname, const xmlChar *revision){ status_t res = NO_ERR;

// … load module, etc.

res = agt_cb_shutdown_register(server_shutdown_cb); return res;}

There is no cleanup function for this callback. The cleanup will be done automatically by the server.

Version 19.10-12 Page 263

Page 264: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.7.2 Shutdown Callback Function Example

The following example code illustrates how the Shutdown callback may look like.

/********************************************************************* FUNCTION server_shutdown_cb** Save the server CLI parms if configured to do that* Either --config=filespec of default config used* If --no-startup used then the changed params will not* be saved on exit or restart** INPUTS:* none* RETURNS:* none********************************************************************/static void server_shutdown_cb (void){ if (!edits_done) { return; }

/* get the run-time values that may have been changed since boot-time */ status_t res = NO_ERR; val_value_t *server_val = agt_init_cache(y_yumaworks_server_M_yumaworks_server, y_yumaworks_server_N_server, &res); if ((server_val == NULL) || (res != NO_ERR)) { if (LOGDEBUG3) { log_debug3("\nyumaworks-server write config skipped " "(no server_val)"); } return; }

/* hack: need container named netconfd-pro, * so use VAL_OBJ for the CLI valset */ val_value_t *cli_val = agt_cli_get_valset(); if (cli_val == NULL) { if (LOGDEBUG3) { log_debug3("\nyumaworks-server write config skipped " "(no cli_val)"); } return; }

/* get the conf filespec */ const xmlChar *confspec = agt_cli_get_confspec(); if (confspec == NULL) { /* --no-config used or no default conf file found */ if (LOGDEBUG3) { log_debug3("\nyumaworks-server write config skipped " "(no confspec)"); } return; }

Version 19.10-12 Page 264

Page 265: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/* make sure the filespec is expanded to an absolute path */ xmlChar *fullspec = ncx_get_source(confspec, &res); if ((fullspec == NULL) || (res != NO_ERR)) { m__free(fullspec); if (res == NO_ERR) { res = ERR_NCX_OPERATION_FAILED; } if (LOGDEBUG) { log_debug("\nyumaworks-server write config skipped " "(get source failed) (%s)", get_error_string(res)); } return; }

/* make a netconfd-pro container */ val_value_t *copyval = val_new_value(); if (copyval == NULL) { m__free(fullspec); return; } val_init_from_template(copyval, VAL_OBJ(cli_val));

/* move all the children */ val_move_children(server_val, copyval);

/* open the config file for writing */ res = log_alt_open_ex((const char *)fullspec, TRUE); // overwrite if (res == NO_ERR) { /* write the value tree as a config file without default leafs */ val_dump_value_full2(copyval, 0, /* startindent */ NCX_DEF_INDENT, /* indent_amount */ DUMP_VAL_ALT_LOG, /* dumpmode */ NCX_DISPLAY_MODE_PLAIN, FALSE, /* withmeta */ TRUE, /* configonly */ TRUE, /* conf_mode */ FALSE, /* expand_varexpr */ FALSE, /* withdef */ DWRT, /* lvl */ NULL); /* overrideOutput */ log_alt_close(); if (LOGDEBUG3) { log_debug3("\nyumaworks-server write config (%s) done", fullspec); } } else { log_warn("\nWarning: config file '%s' could " "not be opened for writing (%s)", fullspec, get_error_string(res)); }

/* move all the CLI parms back */ val_move_children(copyval, server_val);

m__free(fullspec); val_free_value(copyval);

} /* server_shutdown_cb */

Version 19.10-12 Page 265

Page 266: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.8 Command Complete Callback

The Command Complete callback function is a user callback that is invoked when the server has completed an RPC operation and the response has been generated to the client (may not have been sent yet). This callback can be used instead of a command-specific Post-RPC-Reply callback function.

The following function template definition is used for Command Complete callback functions:

/* Typedef of the agt_command_complete_cb_t callback** The Command Complete callback is the user/system callback* that is invoked after each client command is executed* for the NETCONF or RESTCONF protocols.** The Command Complete is typically used for retrieval* operations (get, get-config, get-bulk) to release resources* used during GET2 callbacks invoked during the operation.** Max Callbacks: No limit (except available heap memory)** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* command_modname == YANG module name of command that is completed* command_name == YANG RPC object name of command that is completed** OUTPUTS:* none** RETURNS:* none*/typedef void (*agt_cb_command_complete_t) (ses_cb_t *scb, rpc_msg_t *msg, const xmlChar *command_modname, const xmlChar *command_name);

Callback Template

• Type: User Callback

• Max Callbacks: No limit (except available heap memory)

• File: agt/agt_cb.h

• Template: agt_cb_command_complete_t

◦ Inputs:

▪ scb == session control block

▪ msg == message in progress

▪ command_modname == YANG module name containing the RPC operation

Version 19.10-12 Page 266

Page 267: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

▪ command_name == YANG identifier for the RPC operation

◦ Outputs: none

◦ Returns: none

• Register: agt_cb_command_complete_register

• Unregister: none

Version 19.10-12 Page 267

Page 268: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.8.1 Command Complete Callback Initialization and Cleanup

The agt_cb_command_complete_register function is used to declare the Command Complete callback. The registration can be done during the Initialization Phase 2, before or after the running configuration has been loaded from the startup file.

Initialization function with the Command Complete callback registration may look as follows:

status_t y_example_module_init ( const xmlChar *modname, const xmlChar *revision){ status_t res = NO_ERR;

// … load module, etc.

res = agt_cb_command_complete_register(example_command_complete_cbfn); return res;}

The agt_cb_command_complete_unregister function can be used to remove this callback. This is optional. The server will cleanup automatically on shutdown.

Version 19.10-12 Page 268

Page 269: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.8.2 Command Complete Callback Function Example

The following example code illustrates how the Command Complete callback may look like.

/******************************************************************** FUNCTION example_command_complete_cbfn** The Command Complete callback is the user/system callback* that is invoked after each client command is executed* for the NETCONF or RESTCONF protocols.** The Command Complete is typically used for retrieval* operations (get, get-config, get-bulk) to release resources* used during GET2 callbacks invoked during the operation.** Max Callbacks: No limit (except available heap memory)** INPUTS:* scb == session control block making the request* msg == incoming rpc_msg_t in progress* command_modname == YANG module name of command that is completed* command_name == YANG RPC object name of command that is completed** OUTPUTS:* none** RETURNS:* none*******************************************************************/static void example_command_complete_cbfn (ses_cb_t *scb, rpc_msg_t *msg, const xmlChar *command_modname, const xmlChar *command_name){ (void)command_modname;

if (!xml_strcmp(command_name, (const xmlChar *)"get") || !xml_strcmp(command_name, (const xmlChar *)"get-config") || !xml_strcmp(command_name, (const xmlChar *)"get-bulk")) {

/* cleanup our internal get cache data * example_clean_get2_cache(scb, msg); */ }

}

Version 19.10-12 Page 269

Page 270: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.9 NACM External Groups Callback

The NACM External Groups callback function is a user callback that is invoked when the server creates a new client session for NETCONF or RESTCONF sessions. It is used to retrieve a list of group names that should be used for the specified username, just for that session. These group names are added to any NACM configured groups in the ietf-netconf-acm YANG module.

The following function template definition is used for NACM External Groups callback functions:

/* typedef for NACM External Groups callback function * * Get the list of group names for this username * These groups are added to the usergroup cache for the session * INPUTS: * username: return the list of group names that this username * is a member * retgroups == address of return malloced string * OUTPUTS: * *retgroups is set to a malloced string that will be parsed. * It contains a whitespace delimited list of group named * ' group1 group2 group3' * The caller will free this string with m__free * RETURNS: * status: if an error occurs the session will only use NACM groups */typedef status_t (*agt_acm_group_cbfn_t) (const xmlChar *username, xmlChar **retgroups);

Callback Template

• Type: User Callback

• Max Callbacks: 1

• File: agt/agt_acm_ietf.h

• Template: agt_acm_group_cbfn_t

◦ Inputs:

▪ username == username to find

▪ retgroups == address of return groups list

◦ Outputs:

▪ *retgroups == malloced list of group names (separated by spaces)

◦ Returns: status

• Register: agt_acm_ietf_register_group_cbfn

• Unregister: none

Version 19.10-12 Page 270

Page 271: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.9.1 NACM External Groups Callback Initialization and Cleanup

The agt_acm_ietf_register_group_cbfn function is used to declare the NACM External Group callback. The registrationcan be done during the Initialization Phase 2, before or after the running configuration has been loaded from the startup file.

Initialization function with the NACM External Group callback registration may look as follows:

status_t y_example_module_init ( const xmlChar *modname, const xmlChar *revision){ status_t res = NO_ERR;

// … load module, etc. /* example -- Register a NACM External Groups Callback */ agt_acm_ietf_register_group_cbfn(nacm_external_group_cbfn);

return res;}

There is no unregister function for this callback. The server will cleanup automatically on shutdown.

Version 19.10-12 Page 271

Page 272: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.9.2 NACM External Groups Callback Function Example

The following example code illustrates how the NACM External Group callback may look like.

/********************************************************************* FUNCTION nacm_external_group_cbfn* * Get the list of group names for this username * These groups are added to the usergroup cache for the session * INPUTS: * username: return the list of group names that this username * is a member * retgroups == address of return malloced string * OUTPUTS: * *retgroups is set to a malloced string that will be parsed. * It contains a whitespace delimited list of group named * ' group1 group2 group3' * The caller will free this string with m__free * RETURNS: * status: if an error occurs the session will only use NACM groups*********************************************************************/static status_t nacm_external_group_cbfn (const xmlChar *username, xmlChar **retgroups){ if (retgroups == NULL) { return ERR_NCX_INVALID_VALUE; }

(void)username;

/* MUST use a function that allocates memory with m__getMem * Will be freed by the caller with m__free macro */ *retgroups = xml_strdup("group1 group2 group5"); if (*retgroups == NULL) { return ERR_INTERNAL_MEM; }

return NO_ERR;}

Version 19.10-12 Page 272

Page 273: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.10 Config Replay Callback

The Config Replay callback is a user callback that is invoked when the replay configuration procedure is started and finished. A configuration replay is triggered by a user timer callback function.

When the timer function detects that the back-end system process needs to be reloaded with the current configuration, it needs to call the agt_request_replay() function to cause the server to start the configuration replay procedure.

The following function template definition is used for Config Replay callback functions:

/* Typedef of the callback */ typedef void (*agt_replay_fn_t) (boolean is_start);

Callback Template

• Type: User Callback

• Max Callbacks: 1

• File: agt/agt.h

• Template: agt_replay_fn_t

◦ Inputs:

▪ is_start == TRUE: the configuration replay procedure is starting. FALSE: the configuration replay procedure is finished

◦ Outputs: none

◦ Returns: none

• Register: agt_register_replay_callback

• Unregister: none

Version 19.10-12 Page 273

Page 274: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.11 Periodic Timer Service

Some SIL code may need to be called at periodic intervals to check system status, update counters, and/or perhaps send notifications.

The timer callback function is expected to do a short amount of work, and not block the running process. The function returns zero for a normal exit, and -1 if there was an error and the timer should be destroyed.

A SIL timer can be set up as a periodic timer or a one-time event.

The timer interval (in seconds) and the SIL timer callback function are provided when the timer is created. A timer can alsobe restarted if it is running, and the time interval can be changed as well.

The following table highlights the SIL timer access functions:

SIL Timer Access Functions

Function Description

agt_timer_create Create a SIL timer.

agt_timer_restart Restart a SIL timer

agt_timer_delete Delete a SIL timer

The following function template definition is used for Timer callback functions:

/* Typedef of the callback */ typedef int (*agt_timer_fn_t) (uint32 timer_id,

void *cookie);

Callback Template

• Type: User Callback

• Max Callbacks: 1

• File: agt/agt_timer.h

• Template: agt_timer_fn_t

◦ Inputs:

▪ timer_id == timer identifier

▪ cookie == context pointer, such as a session control block, passed to agt_timer_set function (may be NULL)

◦ Outputs: none

◦ Returns: 0 == normal exit.

-1 == error exit, delete timer upon return

Version 19.10-12 Page 274

Page 275: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

7.11.1 Timed Config Replay Example

It is possible to replay the entire configuration if the underlying system resets or restarts, but the server process is still running.

The configuration replay procedure must be triggered by a timer callback function. This function can be registered in the yp-system library or in a SIL library. The purpose of this callback is to check the health of the underlying system and if it has restarted and needs to be re-initialized with configuration, then the agt_request_replay() function must be called.

/********************************************************************* FUNCTION agt_request_replay** Request replay of the running config to SIL modules* because SIL hardware has reset somehow**********************************************************************/extern void agt_request_replay (void);

The agt_timer_create function is used to declare the callback. The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the registration of the Periodic Timer callback type may look as follows:

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

/* put your module initialization code here */ uint32 timerid = 0;

/* example will check every 10 seconds */ res = agt_timer_create(10, TRUE, force_replay, NULL, &timerid); if (res != NO_ERR) { return res; }

...}

The following example code illustrates how the Periodic Timer callback may look like:

Version 19.10-12 Page 275

Page 276: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

/******************************************************************** * FUNCTION force_replay** Process the timer expired event** INPUTS:* timer_id == timer identifier * cookie == context pointer, such as a session control block,* passed to agt_timer_set function (may be NULL)** RETURNS:* 0 == normal exit* -1 == error exit, delete timer upon return********************************************************************/ static int force_replay (uint32 timer_id, void *cookie){ (void)timer_id; (void)cookie; boolean need_replay = FALSE; // check the system somehow

if (need_replay) { agt_request_replay(); }

return 0;

} /* force_replay */

Now, the Config Replay callback will be invoked when a configuration replay is started or finished, which is triggered by acall to agt_request_replay().

Version 19.10-12 Page 276

Page 277: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

8 RPC Operation CallbacksAll RPC operations are data-driven within the server, using the YANG RPC statement for the operation and SIL callback functions.

Any new protocol operation can be added by defining a new YANG RPC statement in a module, and providing the proper SIL code.

The agt_rpc_method_t function in agt/agt_rpc.h is used as the callback template for all RPC callback phases.

The following function template definition is used for RPC callback function:

/* Template for RPC server callbacks * The same template is used for all RPC callback phases */typedef status_t (*agt_rpc_method_t) (ses_cb_t *scb,

rpc_msg_t *msg, xml_node_t *methnode);

Callback Template

• Type: User Callback

• Max Callbacks: 1 per object

• File: agt_rpc.h

• Template: agt_rpc_method_t

◦ Inputs:

▪ scb == session control block making the request

▪ msg == incoming rpc_msg_t in progress

▪ methnode == XML node for the operation, which can be used in error reporting (or ignored)

◦ Returns: status_tReturn status for the phase; an error in validate phase will cancel Invoke Phase; an rpc-error will be added if anerror is returned and the msg error Q is empty

• Register: agt_rpc_register_method

• Unregister: agt_rpc_unregister_method

Where, scb pointer represents a session control block structure that is defined in the netconf/src/ncx/ses.h. This control block is primarily used for error reporting, as described in the example section later. However, can be used for more advanced actions. It provides access to the session specific information, such as current message input/output encoding, current session ID information, current protocol information, user name information, peer address information, etc. Note, almost all the fields in this structure should NOT be changed and accessed directly. This control block ideally should be used only for getting more information about the current session, not for alteration of any of its fields.

The msg pointer represents the NETCONF Server and Client RPC Request/Reply Message Handler control block that is defined in the netconf/src/ncx/rpc.h. Similarly to SCB, this control block is primarily used for error reporting, as describedin the example section later. However, this control block also provides the RPC input value, as described later in the examples.

Version 19.10-12 Page 277

Page 278: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

The methnode pointer represents the XML node being parsed if this is available. This can used for error reporting if no 'val'or 'obj' parameters are available (from the request message). This pointer is defined in the netconf/src/ncx/xml_util.h.

Version 19.10-12 Page 278

Page 279: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

8.1 RPC Callback Initialization and Cleanup

The agt_rpc_register_method function in agt/agt_rpc.h is used to provide a callback function for a specific callback phase.The same function can be used for multiple phases if desired.

The registration is done during the Initialization Phase 1 before the startup configuration is loaded into the running configuration database and before running configurations are loaded.

Initialization function with the RPC callbacks registration for the Validate Phase may look as follows.

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

res = agt_rpc_register_method (EXAMPLE_MODNAME, (const xmlChar *)"do-example", AGT_RPC_PH_VALIDATE, rpc_example_validate); ...}

Initialization function with the RPC callbacks registration for the Invoke Phase may look as follows.

/******************************************************************** * FUNCTION interfaces_init* * initialize the server instrumentation library.* Initialization Phase 1* *********************************************************************/ static status_t interfaces_init (void) { ...

res = agt_rpc_register_method (EXAMPLE_MODNAME, (const xmlChar *)"do-example", AGT_RPC_PH_INVOKE, rpc_example_validate);

...}

Version 19.10-12 Page 279

Page 280: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

agt_rpc_register_method

Parameter Description

module The name of the module that contains the rpc statement

method_name The identifier for the rpc statement

phase AGT_PH_VALIDATE(0): validate phaseAGT_PH_INVOKE(1): invoke phaseAGT_PH_POST_REPLY(2): post-reply phase

method The address of the callback function to register

If you register a callback for a specific object, your SIL code must unregister it during the cleanup phase, that is being called any time the server is shutting down. Also, it is getting called during restart and reload procedure.

The following example code illustrates how the RPC callback can be cleaned up. The callbacks cleanup is getting done during module Cleanup Phase. This unregister function will clean up callbacks for all the phases and should be called only once per object.

/******************************************************************** * FUNCTION interfaces_cleanup* cleanup the server instrumentation library * ********************************************************************/ void interfaces_cleanup (void){ ...

/* Unregister all the RPC SIL callbacks */ agt_rpc_unregister_method(EXAMPLE_MODNAME, (const xmlChar *)"do-example");

...}

agt_rpc_unregister_method

Parameter Description

module The name of the module that contains the rpc statement

method_name The identifier for the rpc statement

Version 19.10-12 Page 280

Page 281: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

8.2 RPC Callback Function Examples

8.2.1 RPC Validate Callback Function

The RPC Validate callback function is optional to use. Its purpose is to validate any aspects of an RPC operation, beyond the constraints checked by the server engine. Only 1 validate function can register for each YANG RPC statement. The standard NETCONF operations are reserved by the server engine. There is usually zero or one of these callback functions for every 'rpc' statement in the YANG module associated with the SIL code.

The yangdump-sdk code generator will create the SIL callback function by default. There will be C comments in the code to indicate where your additional C code should be added.

The val_find_child function is commonly used to retrieve particular parameters within the RPC input section, which is encoded as a val_value_t tree. The rpc_user1 and rpc_user2 cache pointers in the rpc_msg_t structure can also be used to store data in the Validation phase, so it can be immediately available in the Invoke phase.

The agt_record_error function is commonly used to record any parameter or other errors.

In the following example the callback function validates “session id” value and if it is higher then allowed the operation will report an error and terminate:

/******************************************************************** * FUNCTION rpc_example_validate * * RPC validation phase * All YANG constraints have passed at this point. * * INPUTS: * see agt/agt_rpc.h for details * * RETURNS: * error status ********************************************************************/ static status_t rpc_example_validate (ses_cb_t *scb, rpc_msg_t *msg, xml_node_t *methnode) { status_t res = NO_ERR; val_value_t *errorval = NULL;

if (LOGDEBUG) { log_debug("\nStart SIL validate rpc <do-example> "); }

val_value_t *session_id_val = NULL; uint32 session_id = 0;

val_value_t *inputval = msg->rpc_input;

/* find a session-id child in the RPC input */ session_id_val = val_find_child(inputval, EXAMPLE_MODNAME, (const xmlChar *)"session-id");

if (session_id_val != NULL && session_id_val->res == NO_ERR) {

Version 19.10-12 Page 281

Page 282: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

session_id = VAL_UINT(session_id_val); }

if (session_id) { if (LOGDEBUG) { log_debug("\nSesion ID %u is not acceptable ", session_id); }

/* validate the session ID value */if (session_id > 10) { res = ERR_NCX_OPERATION_NOT_SUPPORTED;}

}

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_OPERATION, res, methnode, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

return res;

} /* rpc_test_augm_validate */

Now, let us go through the most eminent parts of the above example.

In the following part of the above code example we are trying to retrieve the RPC input value, that is stored in the msg->rpc_input and then obtain a needed “session-id” node from the RPC input in order to validate it later:

...

val_value_t *inputval = msg->rpc_input;

/* find a session-id child in the RPC input */ session_id_val = val_find_child(inputval, EXAMPLE_MODNAME, (const xmlChar *)"session-id");

if (session_id_val != NULL && session_id_val->res == NO_ERR) { session_id = VAL_UINT(session_id_val); }

...

In the following part of the above code example we are trying to validate previously retrieved “session-id” value. If the provided in the input value is not acceptable as specified below, then the status_t res pointer will be set to ERR_NCX_OPERATION_NOT_SUPPORTED enumeration value, that would signal to record an error and rterminate the operation.

Version 19.10-12 Page 282

Page 283: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

...

if (session_id) { if (LOGDEBUG) { log_debug("\nSesion ID %u is not acceptable ", session_id); }

/* validate the session ID value */if (session_id > 10) { res = ERR_NCX_OPERATION_NOT_SUPPORTED;}

}

if (res != NO_ERR) { agt_record_error(scb, &msg->mhdr, NCX_LAYER_OPERATION, res, methnode, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval, (errorval) ? NCX_NT_VAL : NCX_NT_NONE, errorval); }

...

Version 19.10-12 Page 283

Page 284: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

8.2.2 RPC Invoke Callback Function

The RPC Invoke callback function is used to perform the operation requested by the client session. Only 1 invoke function can register for each YANG rpc statement. The standard NETCONF operations are reserved by the server engine. There is usually one of these callback functions for every 'rpc' statement in the YANG module associated with the SIL code.

The RPC Invoke callback function is optional to use, although if no invoke callback is provided, then the operation will have no affect. Normally, this is only the case if the module is tested by an application developer, using netconfd-pro as a server simulator.

The yangdump-sdk code generator will create this SIL callback function by default. There will be C comments in the codeto indicate where your additional C code should be added.

The val_find_child function is commonly used to retrieve particular parameters within the RPC input section, which is encoded as a val_value_t tree. The rpc_user1 and rpc_user2 cache pointers in the rpc_msg_t structure can also be used to store data in the Validation phase, so it can be immediately available in the Invoke phase.

The agt_record_error function is commonly used to record any internal or platform-specific errors.

For RPC operations that return either an <ok> or <rpc-error> response, there is nothing more required of the RPC Invoke callback function.

For operations which return some data or <rpc-error>, the SIL code must do 1 of 2 additional tasks:

• add a val_value_t structure to the rpc_dataQ queue in the rpc_msg_t for each parameter listed in the YANG rpc 'output' section.

• set the rpc_datacb pointer in the rpc_msg_t structure to the address of your data reply callback function. See the agt_rpc_data_cb_t definition in agt/agt_rpc.h for more details.

/******************************************************************** * FUNCTION rpc_test_augm_invoke * * RPC invocation phase * All constraints have passed at this point. * Call device instrumentation code in this function. * * INPUTS: * see agt/agt_rpc.h for details * * RETURNS: * error status ********************************************************************/ static status_t rpc_test_augm_invoke (ses_cb_t *scb, rpc_msg_t *msg, xml_node_t *methnode) { status_t res = NO_ERR;

if (LOGDEBUG) { log_debug("\nStart SIL invoke rpc <do-example>"); }

val_value_t *session_id_val = NULL; val_value_t *inputval = msg->rpc_input;

session_id_val = val_find_child(inputval, RPC_TEST_MOD,

Version 19.10-12 Page 284

Page 285: YumaPro API Quick Start Guide · 2020-07-16 · YumaPro API Quick Start Guide 2 YumaPro API Overview This section gives a quick overview for those who want to get started with the

YumaPro API Quick Start Guide

(const xmlChar *)"session-id");

if (session_id_val != NULL && session_id_val->res == NO_ERR) { ; }

/* remove the next line if scb is used */ (void)scb;

/* remove the next line if methnode is used */ (void)methnode;

/* invoke your device instrumentation code here */ return res;

} /* rpc_test_augm_invoke */

Version 19.10-12 Page 285


Recommended