cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
3048
Views
0
Helpful
3
Replies

Nested IF-statements in service template

Hi,

 

I'm working on a l2vpn service-template that requires a nested level of if-statements. In the xml file I first check to determine if the two endpoints are on the same router or on different routers (EoMPLS vs local connection). Within that config section I check if TenGigE or GigE interfaces has been selected;

 

<?if {/link[1]/device != /link[2]/device}?>
  <device tags="nocreate">
    <name>{/link[1]/device}</name>
      <config tags="merge">
        <l2vpn xmlns="http://tail-f.com/ned/cisco-ios-xr" tags="merge">
          <xconnect>
            <group>
              <name>{/customer}</name>
                <p2p>
                  <name>{/name}</name>
                    <interface>
                      <?if {/link[1]/iosxr/xr-GigabitEthernet}?>
                        <name>GigabitEthernet{/link[1]/iosxr/xr-GigabitEthernet}.{/link[1]/link-vlan}</name>
                      <?end?>
                      <?if {/link[1]/iosxr/xr-TenGigabitEthernet}?>
                        <name>TenGigE{/link[1]/iosxr/xr-TenGigabitEthernet}.{/link[1]/link-vlan}</name>
                      <?end?>
                 </interface>
              <neighbor>
                <address>{$PE2}</address>
                <pw-id>{/pw-id}</pw-id>
              </neighbor>
           </p2p>
       </group> 
   </xconnect>
</l2vpn>

...

<?end?>

 

When I perform a packages reload, it completes with the notification of a 'Processing instruction unexpected here' at the line of the second, nested, if statement. Is nested if's unsupported? (I'm running version 4.7).

 

3 Replies 3

rogaglia
Cisco Employee
Cisco Employee

Hi,

The best example of complex template design is located in the example folder from your install:

examples.ncs/service-provider/mpls-vpn-new-template/packages/l3vpn/templates/l3vpn.xml

 

You can see that there are nested if statements.

 

I believe you have a different problem.

 

Roque

I ran into a similar issue and also assumed that nested if-statements wasn't supported. Looking at the l3vpn.xml file you referenced I can see that this was incorrect. It might just be a limitation of how or where you can use if statements. Using the same l3vpn.xml file we have this snippet:

 

<interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
  <?if {starts-with($PE_INT_NAME,'GigabitEthernet')}?>
    <GigabitEthernet-subinterface>
      <GigabitEthernet>
        <id>{substring($PE_INT_NAME,16)}.{$VLAN_ID}</id>
        <description>Link to CE / {$CE} - {$CE_INT_NAME}</description>
        <ipv4>
          <address>
            <ip>{$LINK_PE_ADR}</ip>
            <mask>{$LINK_MASK}</mask>
          </address>
        </ipv4>
        <vrf>{/name}</vrf>
        <encapsulation>
          <dot1q>
            <vlan-id>{$VLAN_ID}</vlan-id>
          </dot1q>
        </encapsulation>
        <service-policy>
          <output>
            <name>{/name}-{$CE}</name>
          </output>
        </service-policy>
      </GigabitEthernet>
    </GigabitEthernet-subinterface>
  <?end?>
  <?if {starts-with($PE_INT_NAME,'TenGigE')}?>
    <TenGigE-subinterface>
      <TenGigE>
        <id>{substring($PE_INT_NAME,8)}.{$VLAN_ID}</id>
        <description>Link to CE / {$CE} - {$CE_INT_NAME}</description>
        <ipv4>
          <address>
            <ip>{$LINK_PE_ADR}</ip>
            <mask>{$LINK_MASK}</mask>
          </address>
        </ipv4>
        <vrf>{/name}</vrf>
        <encapsulation>
          <dot1q>
            <vlan-id>{$VLAN_ID}</vlan-id>
          </dot1q>
        </encapsulation>
        <service-policy>
          <output>
            <name>{/name}-{$CE}</name>
          </output>
        </service-policy>
      </TenGigE>
    </TenGigE-subinterface>
  <?end?>
</interface>

In the above template, we see identical definitions for Gigabit and TenGigabit interfaces. In a template, we might also have Bundle-Ether or 100Gb interfaces. It doesn't seem very efficient to have to redefine every snippet for each interface type. Granted this part of the code is short in this specific template but it can be much longer. The end result is more code to test based on conditional logic where we need to check for more interface types and make sure that the configuration within the snippets is synced.

 

I would like to be able to do something like this instead:

 

<interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
<?if {starts-with($PE_INT_NAME,'GigabitEthernet') or starts-with($PE_INT_NAME,'TenGigE')}?>
  <?if {starts-with($PE_INT_NAME,'GigabitEthernet')}?>
    <GigabitEthernet-subinterface>
        <GigabitEthernet>
  <?end?>
  <?if {starts-with($PE_INT_NAME,'TenGigE')}?>
    <TenGigE-subinterface>
      <TenGigE>
  <?end?>
        <id>{substring($PE_INT_NAME,16)}.{$VLAN_ID}</id>
        <description>Link to CE / {$CE} - {$CE_INT_NAME}</description>
        <ipv4>
          <address>
            <ip>{$LINK_PE_ADR}</ip>
            <mask>{$LINK_MASK}</mask>
          </address>
        </ipv4>
        <vrf>{/name}</vrf>
        <encapsulation>
          <dot1q>
            <vlan-id>{$VLAN_ID}</vlan-id>
          </dot1q>
        </encapsulation>
        <service-policy>
          <output>
            <name>{/name}-{$CE}</name>
          </output>
        </service-policy>
  <?if {starts-with($PE_INT_NAME,'GigabitEthernet')}?>
      </GigabitEthernet>
    </GigabitEthernet-subinterface>
  <?end?>
  <?if {starts-with($PE_INT_NAME,'TenGigE')}?>
      </TenGigE>
    </TenGigE-subinterface>
  <?end?>
<?end?>
</interface>

The above template produces the same error as Johnny described:

 

reload-result {
package l3vpn
result false
info [l3vpn.xml:147 Processing instruction is unexpected here.]

 

<?if {starts-with($PE_INT_NAME,'GigabitEthernet') or starts-with($PE_INT_NAME,'TenGigE')}?>
<?if {starts-with($PE_INT_NAME,'GigabitEthernet')}?>
<GigabitEthernet-subinterface>
<GigabitEthernet>
<?end?> <--- Line 147

 

So, perhaps a better question would be what are the limitations of using the if-statement and how can it currently be used?

Hi, 

I was facing this issue too and realized it had nothing to do with support for nested if statements. The issue here is that the name that you have under interface is a 'key' for the interface list. 

<interface>
    <?if {/link[1]/iosxr/xr-GigabitEthernet}?>
        <name>GigabitEthernet{/link[1]/iosxr/xr-GigabitEthernet}.{/link[1]/link-vlan}</name>

You cannot put conditionals on the key. Instead, you would want to do something like,

<interface when="{/link[1]/iosxr/xr-GigabitEthernet}"?>
        <name>GigabitEthernet{/link[1]/iosxr/xr-GigabitEthernet}.{/link[1]/link-vlan}</name>
<interface when="{/link[1]/iosxr/xr-TenGigabitEthernet}"?>
        <name>TenGigE{/link[1]/iosxr/xr-TenGigabitEthernet}.{/link[1]/link-vlan}</name>

Hope this helps!