This topic explains how to modify the Head-End Router Tunnel Addition template to create multiple tunnels, highlighting the changes made to the default configuration.
This example demonstrates the changes made to the default Head-End Router Tunnel Addition template to create multiple tunnels.
In this example, bold text indicates the changes made to the default Head-End Router Tunnel Addition template to create multiple tunnels:
<#--
Define template variables to keep track of the IAID (IPv4) that was used by
the FAR template when configuring the other end of the tunnel. This template
must use the same IAID in order to locate the same subnet that was leased by
the FAR template so both endpoints are in the matching subnet.
-->
<#assign iaId = 1>
<#--
The same logic is needed for each of the IPsec tunnels, so a macro is used.
-->
<#macro configureTunnel ipSecTunnelSrcInterface ipSecTunnelDestInterface her tunnelIndex ospfCost>
<#--
Only configure the HER tunnel end point if the FAR tunnel end point was
configured. This must match the corresponding logic in the FAR tunnel
template. The tunnel will not have been configured if the WAN interface
does not exist on the FAR or does not have an address assigned to it.
-->
<#assign wanInterface = far.interfaces(ipSecTunnelDestInterface)>
<#if (wanInterface[0].v4.addresses[0].address)??>
<#-- Obtain the full interface name based on the prefix. -->
<#assign interfaceName = wanInterface[0].name>
<#--
Locate a tunnel interface on the HER that is not in use. The template
API provides an unusedInterfaceNumber method for this purpose. All of
the parameters are optional. The first parameter is a name prefix
identifying the type of interfaces, it defaults to "tunnel". The second
parameter is a lower bound on the range the unused interface number must
be in, it defaults to zero. The third parameter is the upper bound on
the range, it defaults to max integer (signed). The method remembers
the unused interface numbers it has returned while the template is
being processed and excludes previously returned numbers. If no unused
interface number meets the constraints an exception will be thrown.
-->
interface Tunnel${her.unusedInterfaceNumber()}
description IPsec tunnel to ${far.eid}
<#assign lease = far.ipv4Subnet(dhcpClientId(far.enDuid, tunnelIndex), far.dhcpV4TunnelLink)>
<#assign iaId = iaId + 1>
ip address ${lease.firstAddress} ${lease.subnetMask}
ip ospf cost ${ospfCost}
ip ospf mtu-ignore
tunnel destination ${wanInterface[0].v4.addresses[0].address}
tunnel mode ipsec ipv4
tunnel protection ipsec profile IPSecProfile
tunnel source ${ipSecTunnelSrcInterface}
no shutdown
exit
router ospf 1
network ${lease.prefix} ${lease.wildcardMask} area ${far.ospfArea1!"1"}
exit
</#if>
</#macro>
<#list far.tunnels("ipSec") as tunnelObject>
<@configureTunnel tunnelObject.ipSecTunnelSrcInterface tunnelObject.ipSecTunnelDestInterface
tunnelObject.her tunnelObject.tunnelIndex 100/>
</#list>
<#--
Configure an IPv6-in-IPv4 GRE tunnel to allow IPv6 traffic to reach the data
center.
-->
<#macro configureGreTunnel greSrcInterface her tunnelIndex>
interface Tunnel${her.unusedInterfaceNumber()}
description GRE IPv6 tunnel to ${far.eid}
<#assign lease = far.ipv6Subnet(far.enDuid, tunnelIndex, far.dhcpV6TunnelLink)>
ipv6 address ${lease.firstAddress}/${lease.prefixLength}
ipv6 enable
ipv6 ospf 2 area ${far.ospfV3Area1!"0"}
ipv6 ospf mtu-ignore
tunnel destination ${far.interfaces("Loopback0")[0].v4.addresses[0].address}
tunnel mode gre ip
tunnel source ${greSrcInterface}
exit
</#macro>
<#-- Loop through the policies for GRE tunnels -->
<#list far.tunnels("gre") as greTunnelObj>
<@configureGreTunnel greTunnelObj.greSrcInterface greTunnelObj.her greTunnelObj.tunnelIndex/>
</#list>