10-31-2018 05:31 AM - edited 10-31-2018 05:33 AM
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).
11-01-2018 06:50 AM
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
11-03-2018 03:10 AM
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?
07-09-2020 12:34 PM
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!
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide