![]() |
libyang
1.0.225
YANG data modeling language library
|
Extensions and user types are supported in the form of plugins. These are loaded from the plugin directory (LIBDIR/libyang/
) whenever a context is created. However, the list of plugins can be refreshed manually by ly_load_plugins(). The extension plugin directory path (default LIBDIR/libyang/extensions/
) can be change via the LIBYANG_EXTENSIONS_PLUGINS_DIR
environment variable and similarly the user type directory (default LIBDIR/libyang/user_types/
) via LIBYANG_USER_TYPES_PLUGINS_DIR
. Note, that unavailable plugins are not removed, only any new plugins are loaded. Also note that the availability of new plugins does not affect the current schemas in the contexts, they are applied only to the newly parsed schemas.
The plugins list can be cleaned by ly_clean_plugins(). However, since various contexts (respectively their schemas) can link to the plugins, the cleanup is successful only when there is no remaining context.
For both plugin types, when a specific plugin is being loaded, libyang checks for the API version the plugin was compiled with. From the plugin side, this is done using LYEXT_VERSION_CHECK
or LYTYPE_VERSION_CHECK
which must be defined in the plugin code.
YANG provides extensions as a mechanism how to add new statements into the language. Since they are very generic - extension instance can appear anywhere, they can contain any other YANG statement including extension instances and their specification has a form of the description text, it is very challenging for libyang to provide working and useful implementation. Therefore, you can reach some limitation regarding the extensions support, but the common use cases should be covered and supported.
Since libyang does not understand human text, it is not possible to get the complete definition of the extension from its description statement. Therefore, libyang allows the schema authors to provide extension plugin that provides information from the extension description to libyang.
Here are some notes about the implementation of the particular YANG extensions features
Extension instance can contain any other YANG statement This is supported with exceptions - the list of YANG statements is defined as LY_STMT enumeration with the description if the specific statement can appear as an extension instance substatement or if there is some limitation regarding its cardinality. It also specifies how the specific statement is stored in the extension instance (which data type or structure is used). In some cases, like include
or yang-version
statements, it make no sense to have them inside an extension instance, so they are not supported by libyang.
The list of allowed substatement for the specific extension instances is provided by the extension plugin. Besides the list of substatement, the plugin also specifies where the data are stored and the cardinality for each substatement. Other extension instances as an extension instance substatements are always allowed. Note, that if there is no extension plugin defined or if the list of the allowed substatements is empty, no substatement (except extension instances) is allowed.
There are several extension types (enumerated as LYEXT_TYPE) according to their purpose and content:
Note that the lys_ext_instance structure serves as a generic structure for all extension instances. In case the lys_ext_instance::ext_type is set to a different value than LYEXT_FLAG, the structure can be cast to the particular extension instance structure to access the type-specific members.
Extension plugins provide more detailed information about the extension in a understandable form for libyang. These information is usually provided in a text form in the extension's description statement. libyang provides several plugins for the common IETF extensions (NACM, Metadata, ...) that can be used as a code examples for other extensions.
There are several types of extension plugins which corresponds to the extension types:
YANG Metadata annotations are defined in RFC 7952 as YANG extension. In practice, it allows to have XML attributes (there is also a special encoding for JSON) in YANG modeled data. libyang does not allow to have any XML attribute without the appropriate annotation definition describing the data as it is done e.g. for leafs. When an attribute without a matching annotation definition is found in the input data, it is silently dropped (with warning) or an error is reported in case the LYD_OPT_STRICT parser option is provided to the parser function.
There are some XML attributes, described by YANG and NETCONF specifications, which are not defined as annotations, but libyang implements them this way. In case of attributes in the YANG namespace (insert
, value
and key
attributes for the NETCONF edit-config operation), they are defined in special libyang's internal module yang
, which is available in each context and the content of this schema can be printed via schema printers.
In case of the attributes described in NETCONF specification, the libyang's annotations structures are hidden and cannot be printed despite, internally, they are part of the ietf-netconf
's schema structure. Therefore, these attributes are available only when the ietf-netconf
schema is loaded in the context. The definitions of these annotations are as follows:
md:annotation operation { type enumeration { enum merge; enum replace; enum create; enum delete; enum remove; } } md:annotation type { type enumeration { enum subtree; enum xpath { if-feature "nc:xpath"; } } } md:annotation select { type string; }
Note, that, following the specification,
type
and select
XML attributes are supposed to be unqualified (without namespace) and thatselect
's content is XPath and it is internally transformed by libyang into the format where the XML namespace prefixes are replaced by the YANG module names.Using this plugin mechanism, it is also possible to define what can be called user types. Values are always stored as a string in addition to being in a lyd_val union. It is possible to customize how the value is stored in the union using a lytype_store_clb callback.
Generally, it is meant for storing certain types more effectively. For instance, when working with ipv4-address from the ietf-inet-types model, an application will most likely use the address in a binary form, not as a string. So, in the callback the value is simply transformed into the desired format and saved into lyd_val value. However, the callback is allowed to store anything in the union. Another example, if there are many strings being created and handled, is to store the string length instead having 2 pointers to the same string.
Also, it is possible to perform some additional validation of the value except for the standard YANG one. Even if the value should only be validated, this callback can be defined and used, it will just keep the lyd_val value unchanged.
There are simple example user type plugins in src/user_types
.