Alter the JUNOS Module to Emit XML-Tagged Output

This chapter explains how to alter your JUNOS module’s C program to emit JUNOScript-tagged output rather than formatted ASCII.

Before using the instructions in this chapter, you must perform the procedures described in Write and Compile the ODL File.

The chapter has the following sections:

Modify the Module Makefile

To enable your module to generate XML-tagged output, add statements to its Makefile file for linking with the following libraries:

Add #include Statements to the Module’s C Program

Perform the following steps to create references in your module’s Makefile file to files that are required for emitting JUNOScript tags:

  1. Add the following statement to your module’s C program to reference the junoscript/xmlrpc.h include file, which defines the JUNOScript macros and prototype functions used to produce JUNOScript-tagged output.

    #include <junoscript/xmlrpc.h>
    

  2. Add a statement for the module_odl.h file, which was generated during compilation of the ODL file. It contains your module’s tag definitions. For example:

    include <odl/module_odl.h>
    

Define Output Destination and Formatting Function

The final required preparation for emitting JUNOScript output is to register two settings in your module’s initialization code. See the indicated sections:

Register the Destination for XML-Tagged Output

Note:
This section does not apply to applications written using the JUNOS SDK.
To register the function that defines where the JUNOScript library is to direct JUNOScript-tagged output from your module, invoke the xml_set_send_method() function in your module’s initialization code. If you do not invoke this function, the JUNOScript library writes the module’s JUNOScript output to stdout. Depending on the destination for your module’s output, register one of the indicated functions:

Register the Formatting Routine

Note:
This section does not apply to applications written using the JUNOS SDK.
To register the function that the JUNOScript library is to use when formatting the contents of the tags being emitted, use the xml_set_vsnprintf_method() function. If you do not call this function, JUNOScript uses the standard C library’s vsnprintf() function. If your module uses a different formatting routine (as does the rpd module), use the following function to register it.

xml_set_vsnprintf_method((xml_vsnprintf_method_t) formatting_function);

Use Macros to Emit JUNOScript Tags

To emit JUNOScript-tagged output, your module invokes the macros described in the following sections. Use these macros in place of the routines previously used to output formatted ASCII.

Common Macro Syntax

The macros for emitting JUNOScript tags are defined in the junoscript/xmlrpc.h file. The macros share the following common syntax. Note the final semicolon.

MACRO (destination, index, list of additional parameters);

MACRO Specifies the kind of tag to emit; it is one of the following:

destination A pointer to the data structure that records the state of your program’s connection with the destination to which it is sending JUNOScript tags. The value to use depends on the kind of program and destination:

  • If your module is a JUNOS daemon running on the router, destination is a variable of type void *. It corresponds to the first parameter in the type definition discussed in Register the Destination for XML-Tagged Output.

    • If the destination is the JUNOS management daemon (mgd), the variable points to a structure of type mgmt_sock_t, indicating that your module uses the mgmt_sock package to communicate with mgd. The most common variable name is peer, which is used in the examples in this section.

    • If the destination is a file (as for the rpd module, for example), the variable points to a structure type specific to the daemon, such as the rpd module’s FILE *.

  • If your program sends its output directly to stdout (as ifinfo does), destination is the value NULL.

index Names the tag to emit, using the tag’s index as recorded in the module_odl.h file. By default, the ODL compiler derives the index from the tag name by making all letters in the tag name uppercase, replacing hyphens with underscores, and affixing the ODCI_ prefix. As an example, the index name for the <traffic-statistics> tag is ODCI_TRAFFIC_STATISTICS. You can use the define statement in the ODL file to specify an alternate index name, as described in Specify a Tag Index Name in Library Files.
list of additional parametersSpecifies one or more additional parameters appropriate for the kind of tag you are defining. For a discussion of the acceptable values, see the following sections.

Emit a Simple Tag with No Attributes

To emit a simple tag that has no attributes, use the XML_ELT macro. The macro’s first two parameters are always the destination and index parameters discussed in Common Macro Syntax.

To include attributes on a simple tag, use the XML_OPEN and XML_CLOSE macros instead of XML_ELT. For more information, see Emit a Container Tag or a Simple Tag with Attributes.

The XML_ELT macro’s third parameter is a printf-style statement that defines the tag’s contents. Usually, the statement includes one or more standard C symbols, such as %s for a string, which represent the actual values that the module substitutes into the string when emitting the tag. The symbol type must match the type of the entity that the module substitutes for it, as specified in the module’s C file. Enclose the complete string in quotation marks ( " " ).

After the third parameter comes one additional parameter for each C symbol in the third parameter, identifying the construct in the module’s C program to substitute for the symbol.

As an example, the following macro emits the <input-bytes> tag. The tag’s contents are the value of the variable ibytes from the module’s C program file. The %qu symbol indicates that the value is a 64-byte unsigned integer.

XML_ELT(peer, ODCI_INPUT_BYTES, "%qu", ptr->ibytes);

The module emits a tag like the following as a result:

<input-bytes>2014</input-bytes>

As another example, the following macro emits the <file> tag. The tag’s content is a filename, which the module represents in its C file as three separate variables (path, file, and extension).

XML_ELT(peer, ODCI_FILE, "%s/%s.%s", path, file, extension);

The module emits a tag like the following as a result:

<file>/var/tmp/snmpd.core</file>

Note:
To avoid unexpected results, do not define any of a JUNOScript tag macro’s parameters to be the direct result of a function. This is especially important when the parameter is a character string of the type normally formatted by a printf-style statement, such as the XML_ELT macro’s third parameter.

As an example, the following code writes the result from the get_my_info() function into a string called buffer, which is then defined as the macro’s third parameter (the contents of the <my-info> tag):

/* DO NOT USE */

char *buffer;

buffer=get_my_info();
XML_ELT(peer, ODCI_MY_INFO, buffer);

The danger is that the buffer string possibly contains percent (%) signs or other characters that have special meaning in a printf-style statement. The renderer’s attempt to interpret the characters as printf symbols will probably fail, causing an error.

As shown in the following, the solution is to use the %s symbol explicitly to define a parameter as a formatted string, and to define buffer as the value to substitute for it.

char *buffer;

buffer=get_my_info();
XML_ELT(peer, ODCI_MY_INFO, "%s", buffer);

Emit an Empty Tag

To emit an empty tag, use the XML_EMPTY macro. The macro’s first two parameters are always the destination and index parameters discussed in Common Macro Syntax. Optionally, you can also define one or more attributes on an empty tag, as described in Assign Attributes to a Tag.

The following example illustrates the macro for an empty tag without attributes.

XML_EMPTY(peer, ODCI_SNMP_TRAP_FLAG);

The module emits the following empty tag.

<snmp-trap-flag/>

Emit a Container Tag or a Simple Tag with Attributes

To emit the opening and closing tags for a container tag element, use the XML_OPEN and XML_CLOSE macros, respectively. Each macro’s first two parameters are always the destination and index parameters discussed in Common Macro Syntax, and the values must match in the two macros. Optionally, the XML_OPEN macro can have one or more attributes as described in Assign Attributes to a Tag.

Also use these macros to emit a simple (noncontainer) tag element that has one or more attributes on its opening tag. The syntax is the same as for a container tag.

The following sample macro emits an opening and closing pair for a tag called <traffic-statistics> which has no attributes. The ellipsis (...) represents the tag pair’s contents, which are omitted here to make the structure of the pair more clear.

XML_OPEN(peer, ODCI_TRAFFIC_STATISTICS);
    ...
XML_CLOSE(peer, ODCI_TRAFFIC_STATISTICS);

The module emits the following tags:

<traffic-statistics>
  ...
</traffic-statistics>

If emitting a simple tag, define its contents by placing either an XML_DATA or XML_OUT macro between the XML_OPEN and XML_CLOSE macros. For examples, see Emit Tag Contents and Assign Attributes to a Tag.

For a container tag, define its child tags by placing sets of nested, paired XML_OPEN and XML_CLOSE macros between the outermost XML_OPEN and XML_CLOSE macros. Usually, the innermost child tags are simple (rather than container) tags, and so are defined by XML_ELT macros (or by paired XML_OPEN and XML_CLOSE macros if the simple tags have attributes).

The following example is a more complete version of the macros for the <traffic-statistics> container tag, which is the child of the <rpc-reply> tag and contains two simple tags, <input-bytes> and <output-bytes>.

XML_OPEN(peer, ODCI_RPC_REPLY);
	XML_OPEN(peer, ODCI_TRAFFIC_STATISTICS);
		XML_ELT(peer, ODCI_INPUT_BYTES, "%u", input-bytes;
		XML_ELT(peer, ODCI_OUTPUT_BYTES, "%u", output-bytes);
	XML_CLOSE(peer, ODCI_TRAFFIC_STATISTICS);
XML_CLOSE(peer, ODCI_RPC_REPLY);

The module emits a tag stream like the following:

<rpc-reply>
	<traffic-statistics>
		<input-bytes>42561</input-bytes>
		<output-bytes>34692</output-bytes>
	</traffic-statistics>
</rpc-reply>

Emit Tag Contents

To emit a simple tag, use either the XML_OUT or XML_DATA macro. Each macro’s first two parameters are always the destination and index parameters discussed in Common Macro Syntax. Both, then, use additional parameters to define the tag’s contents. The distinction between the two macros is as follows:

Note:
The preceding example is presented for the sake of completeness but is actually a bit unrealistic. The main reason to use the XML_OPEN and XML_CLOSE macros for a simple tag instead of XML_ELT or XML_OUT is to include attributes on the tag. For examples of that usage, see Assign Attributes to a Tag.

Assign Attributes to a Tag

You can include one or more attributes, either attributes that you devise or attributes predefined by JUNOScript. on the tags emitted by your program Each attribute is listed as a parameter of an XML_EMPTY or XML_OPEN macro. The appropriate way to reference the attribute differs for user-defined and predefined attributes, as detailed in the following sections:

Assign Attributes That You Define

To include an attribute of your own devising on an XML_EMPTY or XML_OPEN tag, use the XML_ATTR macro. It has the following syntax:

char *XML_ATTR(attr_index , "%s", "attribute_value")

attr_index Names the attribute to emit, identifying it by the index recorded in the modulee_odl.h file. Recall that the ODL compiler derives the index name by adding the suffix. _ATTR_ATTRIBUTE_NAME to the tag’s index name. It derives the ATTRIBUTE_NAME part by converting the name in the ODL attribute statement to all uppercase letters and replacing any hyphens with underscores. For more information, see Assign XML Attributes to a Tag.

As an example, the value for the attribute called heading on the <traffic-statistics> tag is ODCI_TRAFFIC_STATISTICS_ATTR_HEADING (assuming that the tag’s index name has the default form ODCI_TRAFFIC_STATISTICS).

%s Ensures that the subsequent attribute_value is formatted properly.
attribute_value

Specifies the actual value to emit for the attribute. Enclose the value in quotation marks (" ").

The following defines the value Traffic Statistics for the heading attribute on the <traffic-statistics> tag.

XML_OPEN(peer, ODCI_TRAFFIC_STATISTICS, "%s",
   XML_ATTR(ODCI_TRAFFIC_STATISTICS_ATTR_HEADING, "%s", "Traffic Statistics"));

The module emits the following tag as a result:

<traffic-statistics heading="Traffic Statistics">

Assign Predefined JUNOScript Attributes

To include one of the predefined JUNOScript attributes on a tag emitted by your program, reference the appropriate prototype function in an XML_OPEN or XML_EMPTY macro’s list of parameters. The following sections explain how to emit predefined attributes:

Assign the junos:celsius Attribute

The junos:celsius attribute expresses a temperature in degrees Celsius, as discussed in Express a Temperate in Degrees Celsius. The prototype function for including the attribute on an XML_OPEN or XML_EMPTY tag has the following format.

char *xml_attr_celcius (int degrees)

The degrees argument is usually the name of a variable in the module’s C program file that stores the value to emit as the attribute’s value. The following example sets the junos:celcius attribute on the <temperature> tag to the value of the temp_cel variable. Specifying a printf-style statement as the third parameter guarantees that the attribute is formatted properly.

XML_OPEN(peer, ODCI_TEMPERATURE, "%s", xml_attr_celcius(temp_cel));

When the XML_OPEN macro is combined with XML_DATA and XML_CLOSE macros, the module emits the following tag as a result:

<temperature junos:celcius="29">29 degrees C / 84 degrees F</temperature>

Assign the junos:emit Attribute

When the junos:emit attribute is encountered in a field where the emit flag is specified, a newline attribute is emitted. The prototype function for including the attribute on an XML_OPEN tag has the following format:

char *xml_attr_emit (void)

In the following example, the junos:emit attribute is used on the remote MEP count to prevent the CLI rendering from merging with other output. Specifying a printf-style statement as the third parameter guarantees that the attribute is formatted properly.

XML_OPEN(null, ODCI_CFM_REMOTE_MEP_COUNT, "%s", xml_attr_emit())

When the XML_OPEN macro is combined with XML_DATA and XML_CLOSE macros, the module emits the following tag as a result:

<cfm-remote-mep-count junos:emit="emit">

Assign the junos:format Attribute

The junos:format attribute defines a value for the renderer to display that is unrelated to the tag name or contents, as discussed in Display Alternate Text in a Field. The prototype function for including the attribute on an XML_OPEN or XML_EMPTY tag has the following format:

char *xml_attr_format (const char *format)

The format argument is the character string for the renderer to display. The following example defines Enabled as the string for the renderer to display as the value of the junos:format attribute on the <administrative-status> tag. Specifying a printf-style statement as the third parameter guarantees that the attribute is formatted properly.

XML_OPEN(peer, ODCI_ADMINISTRATIVE_STATUS, "%s", xml_attr_format("Enabled"));

When the XML_OPEN macro is combined with XML_DATA and XML_CLOSE macros, the module emits the following tag as a result:

<administrative-status junos:format="Enabled">up</administrative-status>

Assign the junos:seconds Attribute

The junos:seconds attribute expresses a time as a number of seconds, as discussed in Express a Time as a Number of Seconds. The prototype function for including the attribute on an XML_OPEN or XML_EMPTY tag has the following format:

char *xml_attr_seconds (time_t seconds)

The seconds argument is usually the name of a variable in the module’s C program file that stores the value to emit as the value of the attribute. The following example sets the junos:seconds attribute on the <uptime> tag to the value of the up_secs variable. Specifying a printf-style statement as the third parameter guarantees that the attribute is formatted properly.

XML_OPEN(peer, ODCI_UPTIME, "%s", xml_attr_seconds(up_secs));

When the XML_OPEN macro is combined with XML_DATA and XML_CLOSE macros, the module emits the following tag as a result:

<uptime junos:seconds="180">3 minutes</uptime>

Assign the junos:style Attribute

The junos:style attribute specifies which of several formats to use for a tag set, as discussed in Define Multiple Formats for the Same Tags. The prototype function for including the attribute on an XML_OPEN tag has the following format:

char *xml_attr_style (const char *style)

The style argument is the name of the #define statement that the ODL compiler derives from the style statement in the ODL file and records in the module_odl.h file when the odc command line includes the –u option. The compiler bases the #define statement’s name on the name of the tag with which the style is associated, converting all letters in the tag name to uppercase and any hyphens to underscores. It attaches the suffix STYLE_STYLE, where STYLE is the name assigned in the style statement, also converted to all uppercase letters. For more information, see Define Multiple Formats for the Same Tags.

The following example sets the junos:style attribute on the <fpc-information> tag to the value represented by the index FPC_INFORMATION_STYLE_BRIEF. Specifying a printf-style statement as the third parameter guarantees that the attribute is formatted properly.

XML_OPEN(peer, ODCI_FPC_INFORMATION, "%s", xml_attr_style 
    (FPC_INFORMATION_STYLE_BRIEF));

The module emits the following opening tag as a result:

<fpc-information junos:style="brief">

Assign the xmlns Attribute

The xmlns attribute defines the XML namespace to which a tag belongs. The prototype function for including the attribute on an XML_OPEN tag has the following format.

char *xml_attr_xmlns (const char *namespace)

The namespace argument is usually the string XML_NS, which refers to the #define statement of that name in the module_odl.h file, as discussed in About the Namespace Attribute. The following example sets the xmlns attribute on the <interface-information> tag to the conventional value. Specifying a printf-style statement as the third parameter guarantees that the attribute is formatted properly.

XML_OPEN(peer, ODCI_INTERFACE_INFORMATION, "%s", xml_attr_xmlns(XML_NS));

The <interface-information> tag is defined in the junos-interface.dtd file, so for JUNOS Release 5.4 the module emits the following tag as a result:

<interface-information xmlns="http://xml.juniper.net/junos/5.4R1/junos-interface">

Assign Multiple Attributes

You can emit more than one attribute on a tag, in any combination of predefined JUNOScript attributes and attributes defined by you. The following example includes two JUNOScript attributes on the header for the <interface-information> tag:

XML_OPEN(peer, ODCI_INTERFACE_INFORMATION, "%s %s", 
       xml_attr_style(INTERFACE_INFORMATION_STYLE_BRIEF), xmlns(XML_NS));

The module emits the following opening tag as a result:

<interface-information junos:style="brief" 
       xmlns="http://xml.juniper.net/junos/5.4R1/junos-interface">

The following defines the values of two user-defined attributes, heading and size, on the <ospf-database> tag:

XML_OPEN(peer, ODCI_OSPF_DATABASE, "%s %s",
   XML_ATTR(ODCI_OSPF_DATABASE_ATTR_HEADING, "%s", "OSPF link state database"), 
   XML_ATTR(ODCI_OSPF_DATABASE_ATTR_SIZE, "%s", "15000"));

The module emits the following opening tag as a result:

<ospf-database heading="OSPF link state database" size="15000">

The following example combines a JUNOScript attribute, junos:style, and a user-defined attribute, header, on the opening <chassis-information> tag:

XML_OPEN(peer, ODCI_CHASSIS_INFORMATION, "%s %s", 
   xml_attr_style(CHASSIS_INFORMATION_STYLE_DETAILED),
   XML_ATTR(ODCI_CHASSIS_INFORMATION_ATTR_HEADER, "%s", "Chassis information"));

The module emits the following opening tag as a result:

<interface-information junos:style="detailed" header="Chassis information">

© 2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5