Example: Automatically Configuring Logical Interfaces and IP Addresses

Every interface you configure requires at least one logical unit and one IP address. Asynchronous Transfer Mode (ATM) interfaces also require a virtual circuit identifier (VCI) for each logical interface. If you need to configure multiple logical units on an interface, you can use a commit script macro to complete the task quickly and with no errors.

This example expands an apply-macro statement that provides the name of a physical ATM interface, and a set of parameters that specify how to configure a number of logical units on the interface. The units and VCI numbers are numbered sequentially from the $unit variable to the $max variable, and are given IP addresses starting at the $address variable. To loop through the logical units, Extensible Stylesheet Language Transformations (XSLT) uses recursion, which is implemented in the <emit-interface> template. Calculation of the next address is performed in the <next-address> template.

XSLT Syntax

<?xml version="1.0" standalone="yes"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:junos="http://xml.juniper.net/junos/*/junos"
    xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm"
    xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0">
    <xsl:import href="../import/junos.xsl"/>
 
    <xsl:template match="configuration">
        <xsl:for-each select="interfaces/apply-macro">
            <xsl:variable name="device" select="name"/>
            <xsl:variable name="address" select="data[name='address']/value"/>
            <xsl:variable name="max" select="data[name='max']/value"/>
            <xsl:variable name="unit" select="data[name='unit']/value"/>
            <xsl:variable name="real-max">
                <xsl:choose>
                    <xsl:when test="string-length($max) &gt; 0">
                        <xsl:value-of select="$max"/>
                    </xsl:when>
                    <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:variable name="real-unit">
                <xsl:choose>
                    <xsl:when test="string-length($unit) &gt; 0">
                        <xsl:value-of select="$unit"/>
                    </xsl:when>
                    <xsl:when test="contains($device, '.')">
                        <xsl:value-of select="substring-after($device, '.')"/>
                    </xsl:when>
                    <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:variable name="real-device">
                <xsl:choose>
                    <xsl:when test="contains($device, '.')">
                        <xsl:value-of select="substring-before($device, '.')"/>
                    </xsl:when>
                    <xsl:otherwise><xsl:value-of select="$device"/></xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <transient-change>
                <interfaces>
                    <interface>
                        <name><xsl:value-of select="$real-device"/></name>
                        <xsl:call-template name="emit-interface">
                            <xsl:with-param name="address" select="$address"/>
                            <xsl:with-param name="unit" select="$real-unit"/>
                            <xsl:with-param name="max" select="$real-max"/>
                        </xsl:call-template>
                    </interface>
                </interfaces>
            </transient-change>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="emit-interface">
        <xsl:param name="$max"/>
        <xsl:param name="$unit"/>
        <xsl:param name="$address"/>
        <unit>
            <name><xsl:value-of select="$unit"/></name>
            <vci><xsl:value-of select="$unit"/></vci>
            <family>
                <inet>
                    <address><xsl:value-of select="$address"/></address>
                </inet>
            </family>
        </unit>
        <xsl:if test="$max &gt; $unit">
            <xsl:call-template name="emit-interface">
                <xsl:with-param name="address">
                    <xsl:call-template name="next-address">
                        <xsl:with-param name="address" select="$address"/>
                    </xsl:call-template>
                </xsl:with-param>
                <xsl:with-param name="unit" select="$unit + 1"/>
                <xsl:with-param name="max" select="$max"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    <xsl:template name="next-address">
        <xsl:param name="address"/>
        <xsl:variable name="arg-prefix" select="substring-after($address, '/')"/>
        <xsl:variable name="arg-addr" select="substring-before($address, '/')"/>
        <xsl:variable name="addr">
            <xsl:choose>
                <xsl:when test="string-length($arg-addr) &gt; 0">
                    <xsl:value-of select="$arg-addr"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$address"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="prefix">
            <xsl:choose>
                <xsl:when test="string-length($arg-prefix) &gt; 0">
                    <xsl:value-of select="$arg-prefix"/>
                </xsl:when>
                <xsl:otherwise>32</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="a1" select="substring-before($addr, '.')"/>
        <xsl:variable name="a234" select="substring-after($addr, '.')"/>
        <xsl:variable name="a2" select="substring-before($a234, '.')"/>
        <xsl:variable name="a34" select="substring-after($a234, '.')"/>
        <xsl:variable name="a3" select="substring-before($a34, '.')"/>
        <xsl:variable name="a4" select="substring-after($a34, '.')"/>
        <xsl:variable name="r3">
            <xsl:choose>
                <xsl:when test="$a4 &lt; 255">
                    <xsl:value-of select="$a3"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$a3 + 1"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="r4">
            <xsl:choose>
                <xsl:when test="$a4 &lt; 255">
                    <xsl:value-of select="$a4 + 1"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="0"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:value-of select="$a1"/>
        <xsl:text>.</xsl:text>
        <xsl:value-of select="$a2"/>
        <xsl:text>.</xsl:text>
        <xsl:value-of select="$r3"/>
        <xsl:text>.</xsl:text>
        <xsl:value-of select="$r4"/>
        <xsl:text>/</xsl:text>
        <xsl:value-of select="$prefix"/>
    </xsl:template>
</xsl:stylesheet>

SLAX Syntax

version 1.0;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
import "../import/junos.xsl";
 
match configuration {
    for-each (interfaces/apply-macro) {
        var $device = name;
        var $address = data[name='address']/value;
        var $max = data[name='max']/value;
        var $unit = data[name='unit']/value;
        var $real-max = {
            if (string-length($max) > 0) {
                expr $max;
            } else {
                expr "0";
            }
        }
        var $real-unit = {
            if (string-length($unit) > 0) {
                expr $unit;
            } else if (contains($device, '.')) {
                expr substring-after($device, '.');
            } else {
                expr "0";
            }
        }
        var $real-device = {
            if (contains($device, '.')) {
                expr substring-before($device, '.');
            } else {
                expr $device;
            }
        }
        <transient-change> {
            <interfaces> {
                <interface> {
                    <name> $real-device;
                    call emit-interface($address, $unit = $real-unit, $max = $real-max);
                }
            }
        }
    }
}
emit-interface ($max, $unit, $address) {
    <unit> {
        <name> $unit;
        <vci> $unit;
        <family> {
            <inet> {
                <address> $address;
            }
        }
    }
    if ($max > $unit) {
        call emit-interface($unit = $unit + 1, $max) {
            with $address = {
                call next-address($address);
            }
        }
    }
}
next-address ($address) {
    var $arg-prefix = substring-after($address, '/');
    var $arg-addr = substring-before($address, '/');
    var $addr = {
        if (string-length($arg-addr) > 0) {
            expr $arg-addr;
        } else {
            expr $address;
        }
    }
    var $prefix = {
        if (string-length($arg-prefix) > 0) {
            expr $arg-prefix;
        } else {
            expr "32";
        }
    }
    var $a1 = substring-before($addr, '.');
    var $a234 = substring-after($addr, '.');
    var $a2 = substring-before($a234, '.');
    var $a34 = substring-after($a234, '.');
    var $a3 = substring-before($a34, '.');
    var $a4 = substring-after($a34, '.');
    var $r3 = {
        if ($a4 < 255) {
            expr $a3;
        } else {
            expr $a3 + 1;
        }
    }
    var $r4 = {
        if ($a4 < 255) {
            expr $a4 + 1;
        } else {
            expr 0;
        }
    }
    expr $a1;
    expr ".";
    expr $a2;
    expr ".";
    expr $r3;
    expr ".";
    expr $r4;
    expr "/";
    expr $prefix;
}

Testing the ex-atm-logical Script

To test the ex-atm-logical script, perform the following steps:

  1. Copy the XSLT or SLAX script from Example: Automatically Configuring Logical Interfaces and IP Addresses into a text file, name the file ex-atm-logical.xsl or ex-atm-logical.slax as appropriate, and copy it to the /var/db/scripts/commit directory on the device.
  2. Select the following configuration stanzas, and press Ctrl+c to copy them to the clipboard. If you are using the SLAX version of the script, change the filename at the [edit system scripts commit file] hierarchy level to ex-atm-logical.slax.

    system {scripts {commit {allow-transients;file ex-atm-logical.xsl;}}}interfaces {apply-macro at-1/2/3 {address 10.12.13.14/20;max 200;unit 32;}at-1/2/3 {atm-options {pic-type atm2;vpi 0;}}}
  3. In configuration mode, issue the load merge terminal command to merge the stanzas into your device configuration:

    [edit]user@host# load merge terminal[Type ^D at a new line to end input]... Paste the contents of the clipboard here ...
    1. At the prompt, paste the contents of the clipboard using the mouse and the paste icon.
    2. Press Enter.
    3. Press Ctrl+d.
  4. Issue the commit command.

    [edit]
    user@host# commit

When you issue the show interfaces at-1/2/3 | display commit-scripts configuration mode command, the following output appears:

[edit]user@host# show interfaces at-1/2/3 | display commit-scripts atm-options {pic-type atm2;vpi 0;}unit 32 {vci 32;family inet {address 10.12.13.14/20;}}unit 33 {vci 33;family inet {address 10.12.13.15/20;}}unit 34 {vci 34;family inet {address 10.12.13.16/20;}}unit 35 {vci 35;family inet {address 10.12.13.17/20;}}... Logical units 36 through 199 are omitted for brevity ...unit 200 {vci 200 ;family inet {address 10.12.13.182/20;}}