|
| 1 | +{% set host = configuration[hostname] %} |
| 2 | +{% set mgmt_ip = ansible_host %} |
| 3 | +hostname {{ hostname }} |
| 4 | +! |
| 5 | +spanning-tree mode mstp |
| 6 | +! |
| 7 | +aaa root secret 0 123456 |
| 8 | +! |
| 9 | +username admin privilege 15 role network-admin secret 0 123456 |
| 10 | +! |
| 11 | +clock timezone UTC |
| 12 | +! |
| 13 | +lldp run |
| 14 | +lldp management-address Management1 |
| 15 | +! |
| 16 | +snmp-server community {{ snmp_rocommunity }} ro |
| 17 | +! |
| 18 | +ip routing |
| 19 | +ipv6 unicast-routing |
| 20 | +! |
| 21 | +ip route 0.0.0.0/0 {{ mgmt_gw }} |
| 22 | +! |
| 23 | +route-map DEFAULT_ROUTES permit |
| 24 | +! |
| 25 | +{# #} |
| 26 | +{# NOTE: Using large enough values (e.g., podset_number = 200, #} |
| 27 | +{# max_tor_subnet_number = 16, tor_subnet_size = 64), will cause #} |
| 28 | +{# us to overflow the 192.168.0.0/16 private address space here. #} |
| 29 | +{# This should be fine for internal use, but may pose an issue if used otherwise #} |
| 30 | +{# #} |
| 31 | +{% for podset in range(0, props.podset_number) %} |
| 32 | +{% for tor in range(0, props.tor_number) %} |
| 33 | +{% for subnet in range(0, props.tor_subnet_number) %} |
| 34 | +{% set suffix = ( (podset * props.tor_number * props.max_tor_subnet_number * props.tor_subnet_size) + |
| 35 | + (tor * props.max_tor_subnet_number * props.tor_subnet_size) + |
| 36 | + (subnet * props.tor_subnet_size) ) %} |
| 37 | +{% set octet2 = (168 + ((suffix // (256 ** 2))) % 256) %} |
| 38 | +{% set octet3 = ((suffix // 256) % 256) %} |
| 39 | +{% set octet4 = (suffix % 256) %} |
| 40 | +{% set prefixlen_v4 = (32 - ((props.tor_subnet_size | log(2))) | int) %} |
| 41 | +ip route 192.{{ octet2 }}.{{ octet3 }}.{{ octet4 }}/{{ prefixlen_v4 }} {{ props.nhipv4 }} |
| 42 | +ipv6 route 20C0:{{ '%02X%02X' % (octet2, octet3) }}:0:{{ '%02X' % octet4 }}::/64 {{ props.nhipv6 }} |
| 43 | +{% endfor %} |
| 44 | +{% endfor %} |
| 45 | +{% endfor %} |
| 46 | +! |
| 47 | +{% for podset in range(0, props.podset_number) %} |
| 48 | +{% for tor in range(0, props.tor_number) %} |
| 49 | +{% set suffix = ( (podset * props.tor_number * props.max_tor_subnet_number * props.tor_subnet_size) + |
| 50 | + (tor * props.max_tor_subnet_number * props.tor_subnet_size) ) %} |
| 51 | +{% set octet2 = (168 + ((suffix // (256 ** 2))) % 256) %} |
| 52 | +{% set octet3 = ((suffix // 256) % 256) %} |
| 53 | +{% set octet4 = (suffix % 256) %} |
| 54 | +{% set prefixlen_v4 = (32 - (((props.max_tor_subnet_number * props.tor_subnet_size) | log(2)) | int) ) %} |
| 55 | +{% set prefixlen_v6 = (64 - (((props.max_tor_subnet_number * props.tor_subnet_size) | log(2)) | int) ) %} |
| 56 | +ip prefix-list test_ipv4_{{ podset}}_{{ tor }} seq 10 permit 192.{{ octet2 }}.{{ octet3 }}.{{ octet4 }}/{{ prefixlen_v4 }} ge {{ prefixlen_v4 }} |
| 57 | +ipv6 prefix-list test_ipv6_{{ podset}}_{{ tor }} |
| 58 | + seq 10 permit 20C0:{{ '%02X%02X' % (octet2, octet3) }}:0:{{ '%02X' % octet4 }}::/{{ prefixlen_v6 }} ge {{ prefixlen_v6 }} |
| 59 | +exit |
| 60 | +{% endfor %} |
| 61 | +{% endfor %} |
| 62 | +! |
| 63 | +interface Management 1 |
| 64 | + description TO LAB MGMT SWITCH |
| 65 | + ip address {{ mgmt_ip }}/{{ mgmt_prefixlen }} |
| 66 | + no shutdown |
| 67 | +! |
| 68 | +{% for name, iface in host['interfaces'].items() %} |
| 69 | +interface {{ name }} |
| 70 | +{% if name.startswith('Loopback') %} |
| 71 | + description LOOPBACK |
| 72 | +{% else %} |
| 73 | + no switchport |
| 74 | +{% endif %} |
| 75 | +{% if name.startswith('Port-Channel') %} |
| 76 | + port-channel min-links 2 |
| 77 | +{% endif %} |
| 78 | +{% if iface['lacp'] is defined %} |
| 79 | + channel-group {{ iface['lacp'] }} mode active |
| 80 | + lacp rate fast |
| 81 | +{% endif %} |
| 82 | +{% if iface['ipv4'] is defined %} |
| 83 | + ip address {{ iface['ipv4'] }} |
| 84 | +{% endif %} |
| 85 | +{% if iface['ipv6'] is defined %} |
| 86 | + ipv6 enable |
| 87 | + ipv6 address {{ iface['ipv6'] }} |
| 88 | + ipv6 nd ra suppress |
| 89 | +{% endif %} |
| 90 | + no shutdown |
| 91 | +! |
| 92 | +{% endfor %} |
| 93 | +! |
| 94 | +{% for podset in range(0, props.podset_number) %} |
| 95 | +{% if range(0, 1000)|random() >= props.failure_rate %} |
| 96 | +{% for tor in range(0, props.tor_number) %} |
| 97 | +{% set leafasn = props.leaf_asn_start + podset %} |
| 98 | +{% set torasn = props.tor_asn_start + tor %} |
| 99 | +route-map PREPENDAS permit {{ 2 * (podset * props.tor_number + tor + 1) }} |
| 100 | + match ip address prefix-list test_ipv4_{{ podset }}_{{ tor }} |
| 101 | +{% if podset == 0 %} |
| 102 | + set as-path prepend {{ torasn }} |
| 103 | +{% else %} |
| 104 | + set as-path prepend {{ props.spine_asn }} {{ leafasn }} {{ torasn }} |
| 105 | +{% endif %} |
| 106 | +! |
| 107 | +route-map PREPENDAS permit {{ 2 * (podset * props.tor_number + tor + 1) + 1 }} |
| 108 | + match ipv6 address prefix-list test_ipv6_{{ podset }}_{{ tor }} |
| 109 | +{% if podset == 0 %} |
| 110 | + set as-path prepend {{ torasn }} |
| 111 | +{% else %} |
| 112 | + set as-path prepend {{ props.spine_asn }} {{ leafasn }} {{ torasn }} |
| 113 | +{% endif %} |
| 114 | +! |
| 115 | +{% endfor %} |
| 116 | +{% endif %} |
| 117 | +{% endfor %} |
| 118 | +! |
| 119 | +router bgp {{ host['bgp']['asn'] }} |
| 120 | + router-id {{ host['interfaces']['Loopback0']['ipv4'] | ipaddr('address') }} |
| 121 | + ! |
| 122 | +{% for asn, remote_ips in host['bgp']['peers'].items() %} |
| 123 | +{% for remote_ip in remote_ips %} |
| 124 | + neighbor {{ remote_ip }} remote-as {{ asn }} |
| 125 | + neighbor {{ remote_ip }} description {{ asn }} |
| 126 | + neighbor {{ remote_ip }} default-originate route-map DEFAULT_ROUTES |
| 127 | +{% if remote_ip | ipv6 %} |
| 128 | + address-family ipv6 |
| 129 | + neighbor {{ remote_ip }} activate |
| 130 | + exit |
| 131 | +{% endif %} |
| 132 | +{% endfor %} |
| 133 | +{% endfor %} |
| 134 | + ! |
| 135 | +{% for name, iface in host['interfaces'].items() if name.startswith('Loopback') %} |
| 136 | +{% if iface['ipv4'] is defined %} |
| 137 | + network {{ iface['ipv4'] }} |
| 138 | +{% endif %} |
| 139 | +{% if iface['ipv6'] is defined %} |
| 140 | + network {{ iface['ipv6'] }} |
| 141 | +{% endif %} |
| 142 | +{% endfor %} |
| 143 | + redistribute static route-map PREPENDAS |
| 144 | +! |
| 145 | +management api http-commands |
| 146 | + no protocol https |
| 147 | + protocol http |
| 148 | + no shutdown |
| 149 | +! |
| 150 | +end |
| 151 | + |
0 commit comments