SIL External Interface

Each SIL has 2 initialization functions and 1 cleanup function that must be present.

  • The first initialization callback function is used to set up the configuration related objects.

  • The second initialization callback is used to setup up non-configuration objects, after the running configuration has been loaded from the startup file.

  • The cleanup callback is used to remove all SIL data structures and unregister all callback functions.

These are the only SIL functions that the server will invoke directly. They are generated by yangdump-pro with the --format parameter, and usually do not require any editing by the developer.

Most of the work done by SIL code is through callback functions for specific RPC operations and database objects. These callback functions are usually registered during the initialization functions.

The following YANG module will be used for the examples in this section. It is installed as /usr/share/yumapro/modules/test/pass/address.yang

module address {
  namespace "http://www.yumaworks.com/ns/address";
  prefix addr;

  revision "2016-01-22";

  container addresses {
    list address {
      key "last-name first-name";
      leaf last-name {
        type string;
        description
          "Last name of the person who is associated with this address";
      }
      leaf first-name {
        type string;
        description
          "First name of the person who is associated with this address";
      }
      leaf street {
        type string;
        description "street address";
      }
      leaf city {
        type string;
        description "City address";
      }
      leaf zipcode {
        type string { length "5 | 10"; }
        description "zipcode";
      }
      list phone {
        key phone-type;
        leaf phone-type {
          type enumeration {
            enum cell;
            enum home;
            enum work;
          }
        }
        leaf phone-number {
          mandatory true;
          type string;
        }
      }  // list phone
    } // list address
  } // container addresses

} // module address

Stage 1 Initialization

The stage 1 initialization function is the first function called in the library by the server.

This function MUST NOT attempt to access any database. The configuration databases are not ready for access at this time. Use the 'init2' function to adjust the running configuration.

This callback function is expected to perform the following functions:

  • initialize any module static data

  • make sure the requested module name and optional revision date parameters are correct

  • load the requested module name and revision with ncxmod_load_module

  • setup top-level object cache pointers (if needed)

  • register any RPC method callbacks with agt_rpc_register_method

  • register any database object callbacks with agt_cb_register_callback

  • perform any device-specific and/or module-specific initialization

INIT1 Callback Template

Name Format:

y_<modname>_init

Input:

  • modname == string containing module name to load

  • revision == string containing revision date to use. Set to NULL if the operator did not specify a revision.

Returns:

  • operation status (0 if success)

The SIL phase 1 init function uses the following callback template:

typedef status_t (*agt_sil_init_fn_t)(const xmlChar *modname, const xmlChar *revision)

SIL init function template.

Usually loads the module(s) and registers the callbacks

Param modname:

requested module name to load

Param revision:

requested revision date of module to load

Return:

stats

System INIT1 Callback

Example INIT1 function header generated by yangdump-sdk for a system file:

/**
 * @brief Phase 1: Initialize the address server instrumentation library.
 *
 * Called by server when module is loaded.
 *
 * @param modname requested module name to load
 * @param revision requested revision date of the module to load.
 * This may be NULL if the module has no revision statements.
 * @return return status. An error will cause the module load to fail.
 */
extern status_t y_address_init (
    const xmlChar *modname,
    const xmlChar *revision);

Example INIT1 function generated by yangdump-sdk for a system file:

This is a system SIL file representing the mandatory external interface.

/**
 * @brief Phase 1: Initialize the address server instrumentation library.
 *
 * Called by server when module is loaded.
 *
 * @param modname requested module name to load
 * @param revision requested revision date of the module to load.
 * This may be NULL if the module has no revision statements.
 * @return return status. An error will cause the module load to fail.
 */
status_t y_address_init (
    const xmlChar *modname,
    const xmlChar *revision)
{
    status_t res = NO_ERR;

    if (LOGDEBUG) {
        log_debug("\nEnter y_address_init");
    }


    y_addr_init_static_vars();

    /* change if custom handling done */
    if (xml_strcmp(modname, y_addr_M_addr)) {
        return ERR_NCX_UNKNOWN_MODULE;
    }

    if (revision && xml_strcmp(revision, y_addr_R_addr)) {
        return ERR_NCX_WRONG_VERSION;
    }

    res = ncxmod_load_module(
        y_addr_M_addr,
        y_addr_R_addr,
        agt_get_savedevQ(),
        &address_mod);
    if (res != NO_ERR) {
        return res;
    }

    addresses_obj = ncx_find_object(
        address_mod,
        y_addr_N_addresses);
    if (addresses_obj == NULL) {
        return ERR_NCX_DEF_NOT_FOUND;
    }

    res = agt_cb_register_edit2_callback(
        y_addr_M_addr,
        (const xmlChar *)"/addr:addresses",
        y_addr_R_addr,
        addresses_edit);
    if (res != NO_ERR) {
        return res;
    }

    res = agt_cb_register_edit2_callback(
        y_addr_M_addr,
        (const xmlChar *)"/addr:addresses/addr:address",
        y_addr_R_addr,
        address_edit);
    if (res != NO_ERR) {
        return res;
    }

    res = agt_cb_register_edit2_callback(
        y_addr_M_addr,
        (const xmlChar *)"/addr:addresses/addr:address/addr:phone",
        y_addr_R_addr,
        phone_edit);
    if (res != NO_ERR) {
        return res;
    }

    res = u_address_init(modname, revision);
    return res;

} /* y_address_init */

User INIT1 Callback

If the "--split" parameter is used to generate the SIL or SIL-SA code stubs (now the default) then there will be separate "user" C files created (e.g., 'u_address.h' and 'u_address.c').

The platform-specific initialization code for this module should be placed in the "user" file, not the "system" file.

There will be code generated automatically to invoke the User INIT1 callback from the System INIT1 callback.

From This Example:

res = u_address_init(modname, revision);

This is user SIL file representing the optional external interface. You can change the "user" function templates, if desired. These functions are never called by the server directly.

Example INIT1 function header generated by yangdump-sdk for a user file:

/**
 * @brief Phase 1: Initialize the address server instrumentation library.
 *
 * Called by server when module is loaded.
 *
 * @param modname requested module name to load
 * @param revision requested revision date of the module to load.
 * This may be NULL if the module has no revision statements.
 * @return return status. An error will cause the module load to fail.
 */
extern status_t u_address_init (
    const xmlChar *modname,
    const xmlChar *revision);

Example INIT1 function generated by yangdump-sdk for a user file:

/**
 * @brief Phase 1: Initialize the address server instrumentation library.
 *
 * Called by server when module is loaded.
 *
 * @param modname requested module name to load
 * @param revision requested revision date of the module to load.
 * This may be NULL if the module has no revision statements.
 * @return return status. An error will cause the module load to fail.
 */
status_t u_address_init (
    const xmlChar *modname,
    const xmlChar *revision)
{
    status_t res = NO_ERR;

    if (LOGDEBUG) {
        log_debug("\nEnter u_address_init");
    }

    ncx_module_t *address_mod = NULL;

    address_mod = ncx_find_module(modname, revision);
    if (address_mod == NULL) {
        return ERR_NCX_OPERATION_FAILED;
    }

    /* put your module initialization code here */

    return res;

} /* u_address_init */

Stage 2 Initialization

The stage 2 initialization function is the second function called in the library by the server:

  • It will only be called if the stage 1 initialization is called first, and it returns 0 (NO_ERR status).

  • This function is used to initialize any needed data structures in the running configuration, such as factory default configuration, read-only counters and status objects.

  • It is called after the startup configuration has been loaded into the server.

  • If the <load> operation is used during server operation, then this function will be called immediately after the state 1 initialization function.

Note that configuration data structures that are loaded during server initialization will be handled by the database callback functions registered during phase 1 initialization.

Any server-created configuration nodes should be created during phase 2 initialization (this function), after examining the explicitly-provided configuration data. For example, the top-level /nacm container will be created (in agt/agt_acm.c) if it is not provided in the startup configuration.

This callback function is expected to perform the following functions:

  • load non-configuration data structures into the server (if needed)

  • initialize top-level data node cache pointers (if needed)

  • load factory-default configuration data structures into the server (if needed)

  • optionally save a cached pointer to a data tree node (such as the root node for the module). The 'agt_create_cache' function in agt/agt_util.h is used to initialize such a module-static variable.

INIT2 Callback Template

Name Format:

y_<modname>_init2

Returns:

  • operation status (0 if success)

The SIL phase 2 init function uses the following callback template:

typedef status_t (*agt_sil_init2_fn_t)(void)

SIL init2 function template.

Usually sets up post-startup-cfg configuration and monitoring

Return:

status

System INIT2 Callback

Example INIT2 function header generated by yangdump-sdk for a system file:

/**
 * @brief Phase 2: Initialize the address server instrumentation library.
 *
 * SIL init phase 2: non-config data structures.
 * Called after running config is loaded.
 *
 * @return return status. An error will cause the
 * server initialization to fail.
 */
extern status_t y_address_init2 (void);

Example INIT2 function generated by yangdump-sdk for a system file:

/**
 * @brief Phase 2: Initialize the address server instrumentation library.
 *
 * SIL init phase 2: non-config data structures.
 * Called after running config is loaded.
 *
 * @return return status. An error will cause the
 * server initialization to fail.
 */
status_t y_address_init2 (void)
{
    status_t res = NO_ERR;

    if (LOGDEBUG) {
        log_debug("\nEnter y_address_init2");
    }


    addresses_val = agt_init_cache(
        y_addr_M_addr,
        y_addr_N_addresses,
        &res);
    if (res != NO_ERR) {
        return res;
    }

    res = u_address_init2();

    return res;

} /* y_address_init2 */

User INIT2 Callback

If the "--split" parameter was used to generate the SIL or SIL-SA code stubs, then there will be code generated automatically to invoke the User INIT2 callback from the System INIT2 callback.

From This Example:

res = u_address_init2();

This is user SIL file representing the optional external interface. You can change the "user" function templates, if desired. These functions are never called by the server directly.

Example INIT2 function header generated by yangdump-sdk for a user file:

/**
 * @brief Phase 2: Initialize the address server instrumentation library.
 *
 * SIL init phase 2: non-config data structures.
 * Called after running config is loaded.
 *
 * @return return status. An error will cause the
 * server initialization to fail.
 */
extern status_t u_address_init2 (void);

Example INIT2 function generated by yangdump-sdk for a user file:

/**
 * @brief Phase 2: Initialize the address server instrumentation library.
 *
 * SIL init phase 2: non-config data structures.
 * Called after running config is loaded.
 *
 * @return return status. An error will cause the
 * server initialization to fail.
 */
status_t u_address_init2 (void)
{
    status_t res = NO_ERR;

    if (LOGDEBUG) {
        log_debug("\nEnter u_address_init2");
    }


    /* put your init2 code here */

    return res;

} /* u_address_init2 */

Cleanup

The cleanup function is called during server shutdown. It is only called if the stage 1 initialization function is called. It will be called right away if either the stage 1 or stage 2 initialization functions return a non-zero error status.

This callback function is expected to perform the following functions:

  • cleanup any module static data

  • free any top-level object cache pointers (if needed)

  • unregister any RPC method callbacks with 'agt_rpc_unregister_method'

  • unregister any database object callbacks with 'agt_cb_unregister_callbacks'

  • perform any device-specific and/or module-specific cleanup

Cleanup Callback Template

Name Format:

y_<modname>_cleanup

The SIL cleanup function uses the following callback template:

typedef void (*agt_sil_cleanup_fn_t)(void)

SIL cleanup function template.

Usually unloads the module(s) and free any used memory

System Cleanup Callback

Example Cleanup function header generated by yangdump-sdk for a system file:

/**
 * @brief Cleanup the address server instrumentation library.
 *
 * Called by server when module is unloaded.
 *
 */
extern void y_address_cleanup (void);

Example Cleanup function generated by yangdump-sdk for a system file:

/**
 * @brief Cleanup the address server instrumentation library.
 *
 * Called by server when module is unloaded.
 *
 */
void y_address_cleanup (void)
{

    if (LOGDEBUG) {
        log_debug("\nEnter y_address_cleanup");
    }


    agt_cb_unregister_callbacks(
        y_addr_M_addr,
        (const xmlChar *)"/addr:addresses");

    agt_cb_unregister_callbacks(
        y_addr_M_addr,
        (const xmlChar *)"/addr:addresses/addr:address");

    agt_cb_unregister_callbacks(
        y_addr_M_addr,
        (const xmlChar *)"/addr:addresses/addr:address/addr:phone");
    u_address_cleanup();

} /* y_address_cleanup */

User Cleanup Callback

If the "--split" parameter was used to generate the SIL or SIL-SA code stubs, then there will be code generated automatically to invoke the User Cleanup callback from the System Cleanup callback.

From This Example:

res = u_address_cleanup();

This is user SIL file representing the optional external interface. You can change the "user" function templates, if desired. These functions are never called by the server directly.

Example Cleanup function header generated by yangdump-sdk for a user file:

/**
 * @brief Cleanup the address server instrumentation library.
 *
 * Called by server when module is unloaded.
 *
 */
extern void u_address_cleanup (void);

Example Cleanup function generated by yangdump-sdk for a user file:

/**
 * @brief Cleanup the address server instrumentation library.
 *
 * Called by server when module is unloaded.
 *
 */
void u_address_cleanup (void)
{

    if (LOGDEBUG) {
        log_debug("\nEnter u_address_cleanup");
    }


    /* put your cleanup code here */

} /* u_address_cleanup */