{% macro if_name(n) -%}
{{- (('oc_%s/1_0' if sros_use_openconfig|default(true) else 'i%s' if n[0].isdigit() else '%s')|format(n)).replace(':','_') -}}
{%- endmacro %}

{% macro declare_router(i,sub_path="") -%}
{%  set service_name = i.vrf if i.vrf is defined else 'default' %}
{%  set in_base = i.vrf is not defined and (i.vlan is not defined or i.vlan.mode|default('irb')=='route') %}
{%  set base_path = "router[router-name=Base]" if in_base else "service/vprn[service-name="+service_name+"]" %}

{# Minimal service config must exist #}
{%  if not in_base %}
- path: configure/{{ base_path }}
  val:
   service-id: {{ vrfs[i.vrf].vrfidx if i.vrf is defined else 1 }}
   customer: "1"
   admin-state: enable
   ecmp: 64
{%  endif %}

- path: configure/{{ base_path }}{{ sub_path }}
{%- endmacro %}

{% macro declare_interface(i,name=None) %}
{% set name = name or i.ifname %}
{% set ifname = (('oc_%s/1_0' if sros_use_openconfig|default(true) else 'i%s' if name[0].isdigit() else '%s')|format(name)).replace(':','_') %}
{{ declare_router(i,sub_path="/interface[interface-name=" + ifname + "]") }}
{% endmacro %}

{% macro ip_addr(v,ip,ifname) %}
{% set _ip = ip|ipaddr('address') %}
{% set _pre = ip|ipaddr('prefix') %}
   ipv{{v}}:
{% if v=='4' %}
    primary:
     address: "{{ _ip }}"
     prefix-length: {{ _pre }}
{% else %}
    address:
    - ipv6-address: "{{ _ip }}"
      prefix-length: {{ 128 if ifname=='system' else _pre }}
{% endif %}
{% endmacro %}

{% macro interface(name,desc,ip_v4,ip_v6,port,l,vlan=0) -%}
{{ declare_interface(l,name) }}
  val:
   admin-state: enable
   description: "{{ desc }} vlan={{vlan}}"
{% if port %}
{%  if l.vrf is defined %}
   sap:
   - sap-id: "{{ port }}"
{%  else %}
   port: "{{ port }}"
{%  endif %}
{% elif name!='system' and l.type in ['loopback','stub'] %}
   loopback: {{ True if l.vrf is defined else [null] }}
{% endif %}
{% if ip_v4 is string and ip_v4|ipv4 %}
{{  ip_addr('4',ip_v4,name) }}
{% elif ip_v4 == True %}
   ipv4:
    unnumbered:
{%  if l.vrf is defined and loopback.ipv4|default('')|ipv4 %}
     ip-address: {{ loopback.ipv4|ipaddr('address') }}
{%  else %}
     system: [null]
{%  endif %}
{% endif %}
{% if ip_v6 is string and ip_v6|ipv6 %}
{{ ip_addr('6',ip_v6,name) }}
{% elif ip_v6 == True %}
   ipv6: { }
{% endif %}
{%- endmacro -%}

{% macro port(l,vlan=0,tagged=False,native=False) %}
{%  set v4 = l.ipv4|default(False) %}
{%  set v6 = l.ipv6|default(False) %}
{%  set in_base = l.vrf is not defined and (l.vlan is not defined or l.vlan.mode|default('irb')=='route') %}

{%  if l.name is defined %}
{%   set desc = l.name|replace('->','~') + " (" + l.role|default('') + ")" %}
{%  elif l.type|default("") == "stub" %}
{%   set desc = "Stub interface" %}
{%  endif %}

{%  set portname = l.parent_ifname if l.type=='vlan_member' else l.ifname %}
{%  if l.type in ['p2p','lan','vlan_member'] %}
{%   if 'c' in portname %}
- path: configure/port[port-id={{portname}}]
  val:
   connector:
    breakout: "c1-100g"
{%    set portname = portname + '/1' %}
- path: configure/port[port-id={{ portname }}]
  val:
{%   endif %}
   ethernet:
{%   set eth_header = 14 + (4 if tagged else 0) %}
{%   if l.mtu is defined and l.mtu <= (9800-eth_header) %}
    mtu: {{ l.mtu + eth_header }} # max 9800
{%   endif %}
{%   if l.vlan.trunk_id is defined or (l.parent_ifindex is defined and interfaces[l.parent_ifindex-1].vlan.trunk_id is defined) %}
    mode: hybrid # Support mixed trunks by using hybrid ports
{%   elif not in_base %}
    mode: access
{%   else %}
    mode: network
{%   endif %}
{%   if tagged %}
{%     set portname = portname + ':' + vlan|string %}
    encap-type: dot1q
{%   endif %}
{%  endif %}

{% if v4 or v6 %}
{%  if l.type not in ['loopback','stub','svi'] %}
{{ interface(l.ifname,desc,v4,v6,portname,l,vlan=vlan) }}
{%  else %}
{{ interface("stub-"+l.ifname if l.type=='stub' else l.ifname,desc,v4,v6,None,l) }}
{%  endif %}
{% endif %}
{%- endmacro -%}

updates:
{% if 'ixr' in clab.type %}
- path: configure/system/resource
  val:
   ecmp-profile:
   - profile-id: 1
     type: ip # or mpls
     links: 16
     groups: 64
{% endif %}

{# Enable ECMP=64 by default #}
- path: configure/router[router-name=Base]
  val:
   ecmp: {{ 1 if 'ixr' in clab.type else 64 }}

{% if loopback.ipv4|default('')|ipv4 or 'ipv6' in loopback %}
{% set _v4 = loopback.ipv4|default(False) %}
{% set _v6 = loopback.ipv6|default(False) %}
{# The interface name 'system' is special, also used for IP unnumbered #}
{{ interface("system","system interface",_v4,_v6,port=None,l=loopback) }}
{% endif %}

{% for l in (interfaces|default([])) if l.vlan is not defined and l.subif_index is not defined %}
{{  port(l) }}
{% endfor %}
