[bgpcfgd]: Split default bgp config into main config and peer template (#3627)
Now it's possible to add and remove peers based on ConfigDB - What I did Fixed functionality for dynamically adding/removing static bgp peers. - How I did it Split the bgp default template on bgp part and bgp peer part Changed bgpcfgd to use 1. - How to verify it Build an image and run on your DUT
This commit is contained in:
parent
e883d35ce1
commit
8457248d01
@ -1,32 +1,104 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import copy
|
||||
import Queue
|
||||
import redis
|
||||
import subprocess
|
||||
import datetime
|
||||
import time
|
||||
import syslog
|
||||
import signal
|
||||
import traceback
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from pprint import pprint
|
||||
|
||||
import jinja2
|
||||
import netaddr
|
||||
from swsscommon import swsscommon
|
||||
|
||||
|
||||
def run_command(command):
|
||||
syslog.syslog(syslog.LOG_DEBUG, "execute command {}.".format(command))
|
||||
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
|
||||
stdout = p.communicate()[0]
|
||||
p.wait()
|
||||
g_run = True
|
||||
g_debug = False
|
||||
|
||||
|
||||
def run_command(command, shell=False):
|
||||
str_cmd = " ".join(command)
|
||||
if g_debug:
|
||||
syslog.syslog(syslog.LOG_DEBUG, "execute command {}.".format(str_cmd))
|
||||
p = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if p.returncode != 0:
|
||||
syslog.syslog(syslog.LOG_ERR, 'command execution returned {}. Command: "{}", stdout: "{}"'.format(p.returncode, command, stdout))
|
||||
syslog.syslog(syslog.LOG_ERR, 'command execution returned {}. Command: "{}", stdout: "{}", stderr: "{}"'.format(p.returncode, str_cmd, stdout, stderr))
|
||||
|
||||
return p.returncode, stdout, stderr
|
||||
|
||||
class TemplateFabric(object):
|
||||
def __init__(self):
|
||||
j2_template_paths = ['/usr/share/sonic/templates']
|
||||
j2_loader = jinja2.FileSystemLoader(j2_template_paths)
|
||||
j2_env = jinja2.Environment(loader=j2_loader, trim_blocks=True)
|
||||
j2_env.filters['ipv4'] = self.is_ipv4
|
||||
j2_env.filters['ipv6'] = self.is_ipv6
|
||||
self.env = j2_env
|
||||
|
||||
def from_file(self, filename):
|
||||
return self.env.get_template(filename)
|
||||
|
||||
def from_string(self, tmpl):
|
||||
return self.env.from_string(tmpl)
|
||||
|
||||
@staticmethod
|
||||
def is_ipv4(value):
|
||||
if not value:
|
||||
return False
|
||||
if isinstance(value, netaddr.IPNetwork):
|
||||
addr = value
|
||||
else:
|
||||
try:
|
||||
addr = netaddr.IPNetwork(str(value))
|
||||
except:
|
||||
return False
|
||||
return addr.version == 4
|
||||
|
||||
@staticmethod
|
||||
def is_ipv6(value):
|
||||
if not value:
|
||||
return False
|
||||
if isinstance(value, netaddr.IPNetwork):
|
||||
addr = value
|
||||
else:
|
||||
try:
|
||||
addr = netaddr.IPNetwork(str(value))
|
||||
except:
|
||||
return False
|
||||
return addr.version == 6
|
||||
|
||||
|
||||
class BGPConfigManager(object):
|
||||
def __init__(self, daemon):
|
||||
self.daemon = daemon
|
||||
self.bgp_asn = None
|
||||
self.bgp_message = Queue.Queue(0)
|
||||
self.meta = None
|
||||
self.bgp_messages = []
|
||||
self.peers = self.load_peers() # we can have bgp monitors peers here. it could be fixed by adding support for it here
|
||||
fabric = TemplateFabric()
|
||||
self.bgp_peer_add_template = fabric.from_file('bgpd.peer.conf.j2')
|
||||
self.bgp_peer_del_template = fabric.from_string('no neighbor {{ neighbor_addr }}')
|
||||
self.bgp_peer_shutdown = fabric.from_string('neighbor {{ neighbor_addr }} shutdown')
|
||||
self.bgp_peer_no_shutdown = fabric.from_string('no neighbor {{ neighbor_addr }} shutdown')
|
||||
daemon.add_manager(swsscommon.CONFIG_DB, swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, self.__metadata_handler)
|
||||
daemon.add_manager(swsscommon.CONFIG_DB, swsscommon.CFG_BGP_NEIGHBOR_TABLE_NAME, self.__bgp_handler)
|
||||
|
||||
def load_peers(self):
|
||||
peers = set()
|
||||
command = ["vtysh", "-c", "show bgp neighbors json"]
|
||||
rc, out, err = run_command(command)
|
||||
if rc == 0:
|
||||
js_bgp = json.loads(out)
|
||||
peers = set(js_bgp.keys())
|
||||
return peers
|
||||
|
||||
def __metadata_handler(self, key, op, data):
|
||||
if key != "localhost" \
|
||||
or "bgp_asn" not in data \
|
||||
@ -35,90 +107,144 @@ class BGPConfigManager(object):
|
||||
|
||||
# TODO add ASN update commands
|
||||
|
||||
self.meta = { 'localhost': data }
|
||||
self.bgp_asn = data["bgp_asn"]
|
||||
self.__update_bgp()
|
||||
|
||||
def __update_bgp(self):
|
||||
while not self.bgp_message.empty():
|
||||
key, op, data = self.bgp_message.get()
|
||||
syslog.syslog(syslog.LOG_INFO, 'value for {} changed to {}'.format(key, data))
|
||||
cmds = []
|
||||
for key, op, data in self.bgp_messages:
|
||||
if op == swsscommon.SET_COMMAND:
|
||||
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} remote-as {}'".format(self.bgp_asn, key, data['asn'])
|
||||
run_command(command)
|
||||
if "name" in data:
|
||||
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} description {}'".format(self.bgp_asn, key, data['name'])
|
||||
run_command(command)
|
||||
if key not in self.peers:
|
||||
cmds.append(self.bgp_peer_add_template.render(DEVICE_METADATA=self.meta, neighbor_addr=key, bgp_session=data))
|
||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} added with attributes {}'.format(key, data))
|
||||
self.peers.add(key)
|
||||
else:
|
||||
# when the peer is already configured we support "shutdown/no shutdown"
|
||||
# commands for the peers only
|
||||
if "admin_status" in data:
|
||||
command_mod = "no " if data["admin_status"] == "up" else ""
|
||||
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c '{}neighbor {} shutdown'".format(self.bgp_asn, command_mod, key)
|
||||
run_command(command)
|
||||
if data['admin_status'] == 'up':
|
||||
cmds.append(self.bgp_peer_no_shutdown.render(neighbor_addr=key))
|
||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "up"'.format(key))
|
||||
elif data['admin_status'] == 'down':
|
||||
cmds.append(self.bgp_peer_shutdown.render(neighbor_addr=key))
|
||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "down"'.format(key))
|
||||
else:
|
||||
syslog.syslog(syslog.LOG_ERR, "Peer {}: Can't update the peer. has wrong attribute value attr['admin_status'] = '{}'".format(key, data['admin_status']))
|
||||
else:
|
||||
syslog.syslog(syslog.LOG_INFO, "Peer {}: Can't update the peer. No 'admin_status' attribute in the request".format(key))
|
||||
elif op == swsscommon.DEL_COMMAND:
|
||||
# Neighbor is deleted
|
||||
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {}'".format(self.bgp_asn, key)
|
||||
run_command(command)
|
||||
if key in self.peers:
|
||||
cmds.append(self.bgp_peer_del_template.render(neighbor_addr=key))
|
||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} has been removed'.format(key))
|
||||
self.peers.remove(key)
|
||||
else:
|
||||
syslog.syslog(syslog.LOG_WARNING, 'Peer {} is not found'.format(key))
|
||||
self.bgp_messages = []
|
||||
|
||||
if len(cmds) == 0:
|
||||
return
|
||||
|
||||
fd, tmp_filename = tempfile.mkstemp(dir='/tmp')
|
||||
os.close(fd)
|
||||
with open (tmp_filename, 'w') as fp:
|
||||
fp.write('router bgp %s\n' % self.bgp_asn)
|
||||
for cmd in cmds:
|
||||
fp.write("%s\n" % cmd)
|
||||
|
||||
command = ["vtysh", "-f", tmp_filename]
|
||||
run_command(command) #FIXME
|
||||
os.remove(tmp_filename)
|
||||
|
||||
def __bgp_handler(self, key, op, data):
|
||||
self.bgp_message.put((key, op, data))
|
||||
self.bgp_messages.append((key, op, data))
|
||||
# If ASN is not set, we just cache this message until the ASN is set.
|
||||
if self.bgp_asn == None:
|
||||
return
|
||||
if self.bgp_asn is not None:
|
||||
self.__update_bgp()
|
||||
|
||||
|
||||
class Daemon(object):
|
||||
|
||||
SELECT_TIMEOUT = 1000
|
||||
SUPPORT_DATABASE_LIST = (swsscommon.APPL_DB, swsscommon.CONFIG_DB)
|
||||
DATABASE_LIST = [ swsscommon.CONFIG_DB ]
|
||||
|
||||
def __init__(self):
|
||||
self.appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
|
||||
self.conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
|
||||
self.db_connectors = { db : swsscommon.DBConnector(db, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0) for db in Daemon.DATABASE_LIST }
|
||||
self.selector = swsscommon.Select()
|
||||
self.db_connectors = {}
|
||||
self.callbacks = {}
|
||||
self.callbacks = defaultdict(lambda : defaultdict(list)) # db -> table -> []
|
||||
self.subscribers = set()
|
||||
|
||||
def get_db_connector(self, db):
|
||||
if db not in Daemon.SUPPORT_DATABASE_LIST:
|
||||
raise ValueError("database {} not Daemon support list {}.".format(db, SUPPORT_DATABASE_LIST))
|
||||
# if this database connector has been initialized
|
||||
if db not in self.db_connectors:
|
||||
self.db_connectors[db] = swsscommon.DBConnector(db, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
|
||||
return self.db_connectors[db]
|
||||
|
||||
def add_manager(self, db, table_name, callback):
|
||||
if db not in self.callbacks:
|
||||
self.callbacks[db] = {}
|
||||
if db not in Daemon.DATABASE_LIST:
|
||||
raise ValueError("database {} isn't supported. Supported '{}' only.".format(db, ",".join(Daemon.DATABASE_LIST)))
|
||||
|
||||
if table_name not in self.callbacks[db]:
|
||||
self.callbacks[db][table_name] = []
|
||||
conn = self.get_db_connector(db)
|
||||
conn = self.db_connectors[db]
|
||||
subscriber = swsscommon.SubscriberStateTable(conn, table_name)
|
||||
self.subscribers.add(subscriber)
|
||||
self.selector.addSelectable(subscriber)
|
||||
self.callbacks[db][table_name].append(callback)
|
||||
|
||||
def start(self):
|
||||
while True:
|
||||
state, selectable = self.selector.select(Daemon.SELECT_TIMEOUT)
|
||||
if not selectable:
|
||||
def run(self):
|
||||
while g_run:
|
||||
state, _ = self.selector.select(Daemon.SELECT_TIMEOUT)
|
||||
if state == self.selector.TIMEOUT:
|
||||
continue
|
||||
elif state == self.selector.ERROR:
|
||||
raise Exception("Received error from select")
|
||||
|
||||
for subscriber in self.subscribers:
|
||||
key, op, fvs = subscriber.pop()
|
||||
# if no new message
|
||||
if not key:
|
||||
continue
|
||||
data = dict(fvs)
|
||||
syslog.syslog(syslog.LOG_DEBUG, "Receive message : {}".format((key, op, fvs)))
|
||||
if g_debug:
|
||||
syslog.syslog(syslog.LOG_DEBUG, "Received message : {}".format((key, op, fvs)))
|
||||
for callback in self.callbacks[subscriber.getDbConnector().getDbId()][subscriber.getTableName()]:
|
||||
callback(key, op, data)
|
||||
callback(key, op, dict(fvs))
|
||||
|
||||
|
||||
def wait_for_bgpd():
|
||||
# wait for 20 seconds
|
||||
stop_time = datetime.datetime.now() + datetime.timedelta(seconds=20)
|
||||
syslog.syslog(syslog.LOG_INFO, "Start waiting for bgpd: %s" % str(datetime.datetime.now()))
|
||||
while datetime.datetime.now() < stop_time:
|
||||
rc, out, err = run_command(["vtysh", "-c", "show daemons"])
|
||||
if rc == 0 and "bgpd" in out:
|
||||
syslog.syslog(syslog.LOG_INFO, "bgpd connected to vtysh: %s" % str(datetime.datetime.now()))
|
||||
return
|
||||
time.sleep(0.1) # sleep 100 ms
|
||||
raise RuntimeError("bgpd hasn't been started in 20 seconds")
|
||||
|
||||
|
||||
def main():
|
||||
syslog.openlog("bgpcfgd")
|
||||
wait_for_bgpd()
|
||||
daemon = Daemon()
|
||||
bgp_manager = BGPConfigManager(daemon)
|
||||
daemon.start()
|
||||
syslog.closelog()
|
||||
daemon.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
def signal_handler(signum, frame):
|
||||
global g_run
|
||||
g_run = False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
rc = 0
|
||||
try:
|
||||
syslog.openlog('bgpcfgd')
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
syslog.syslog(syslog.LOG_NOTICE, "Keyboard interrupt")
|
||||
except RuntimeError as e:
|
||||
syslog.syslog(syslog.LOG_CRIT, "%s" % str(e))
|
||||
rc = -2
|
||||
except Exception as e:
|
||||
syslog.syslog(syslog.LOG_CRIT, "Got an exception %s: Traceback: %s" % (str(e), traceback.format_exc()))
|
||||
rc = -1
|
||||
finally:
|
||||
syslog.closelog()
|
||||
try:
|
||||
sys.exit(rc)
|
||||
except SystemExit:
|
||||
os._exit(rc)
|
||||
|
@ -1,3 +1,4 @@
|
||||
!
|
||||
{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %}
|
||||
{% block bgp_init %}
|
||||
!
|
||||
@ -12,7 +13,7 @@ route-map TO_BGP_SPEAKER_V4 deny 10
|
||||
{% if prefix | ipv4 and name == 'Loopback0' %}
|
||||
ip prefix-list PL_LoopbackV4 permit {{ prefix | ip }}/32
|
||||
{% elif prefix | ipv6 and name == 'Loopback0' %}
|
||||
ipv6 prefix-list PL_LoopbackV6 permit {{ prefix | ip }}/64
|
||||
ipv6 prefix-list PL_LoopbackV6 permit {{ prefix | replace('/128', '/64') | ip_network }}/64
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
!
|
||||
@ -28,6 +29,13 @@ route-map FROM_BGPMON_V4 deny 10
|
||||
route-map TO_BGPMON_V4 permit 10
|
||||
!
|
||||
{% endif %}
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
bgp log-neighbor-changes
|
||||
bgp bestpath as-path multipath-relax
|
||||
@ -65,63 +73,32 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock vlan_advertisement %}
|
||||
{% block bgp_sessions %}
|
||||
{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %}
|
||||
{% if bgp_session['asn'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }}
|
||||
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
|
||||
{# set the bgp neighbor timers if they have not default values #}
|
||||
{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60)
|
||||
or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %}
|
||||
neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }}
|
||||
{% endif %}
|
||||
{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %}
|
||||
neighbor {{ neighbor_addr }} shutdown
|
||||
{% endif %}
|
||||
{# Apply default route-map for v4 peers #}
|
||||
{% if neighbor_addr | ipv4 %}
|
||||
neighbor {{ neighbor_addr }} route-map TO_BGP_PEER_V4 out
|
||||
{% endif %}
|
||||
{% if neighbor_addr | ipv4 %}
|
||||
{% block maximum_paths %}
|
||||
address-family ipv4
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
address-family ipv6
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
{% endblock maximum_paths %}
|
||||
{% block peers_peer_group %}
|
||||
neighbor PEER_V4 peer-group
|
||||
neighbor PEER_V6 peer-group
|
||||
address-family ipv4
|
||||
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
|
||||
neighbor {{ neighbor_addr }} allowas-in 1
|
||||
neighbor PEER_V4 allowas-in 1
|
||||
{% endif %}
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
|
||||
{% if bgp_session['rrclient'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} route-reflector-client
|
||||
{% endif %}
|
||||
{% if bgp_session['nhopself'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} next-hop-self
|
||||
{% endif %}
|
||||
maximum-paths 64
|
||||
neighbor PEER_V4 soft-reconfiguration inbound
|
||||
neighbor PEER_V4 route-map TO_BGP_PEER_V4 out
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% if neighbor_addr | ipv6 %}
|
||||
address-family ipv6
|
||||
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
|
||||
neighbor {{ neighbor_addr }} allowas-in 1
|
||||
neighbor PEER_V6 allowas-in 1
|
||||
{% endif %}
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
|
||||
{% if bgp_session['rrclient'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} route-reflector-client
|
||||
{% endif %}
|
||||
{% if bgp_session['nhopself'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} next-hop-self
|
||||
{% endif %}
|
||||
{% if bgp_session['asn'] != DEVICE_METADATA['localhost']['bgp_asn'] %}
|
||||
neighbor {{ neighbor_addr }} route-map set-next-hop-global-v6 in
|
||||
{% endif %}
|
||||
{# Apply default route-map for v6 peers #}
|
||||
neighbor {{ neighbor_addr }} route-map TO_BGP_PEER_V6 out
|
||||
maximum-paths 64
|
||||
neighbor PEER_V6 soft-reconfiguration inbound
|
||||
neighbor PEER_V6 route-map TO_BGP_PEER_V6 out
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock bgp_sessions %}
|
||||
{% endblock peers_peer_group %}
|
||||
{% block bgp_peers_with_range %}
|
||||
{% if BGP_PEER_RANGE %}
|
||||
{% for bgp_peer in BGP_PEER_RANGE.values() %}
|
||||
@ -150,11 +127,9 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
{% endfor %}
|
||||
address-family ipv4
|
||||
neighbor {{ bgp_peer['name'] }} activate
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
address-family ipv6
|
||||
neighbor {{ bgp_peer['name'] }} activate
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
@ -6,28 +6,13 @@
|
||||
!
|
||||
{% endblock banner %}
|
||||
!
|
||||
{% block system_init %}
|
||||
hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
|
||||
password zebra
|
||||
log syslog informational
|
||||
log facility local4
|
||||
{% include "daemons.common.conf.j2" %}
|
||||
!
|
||||
agentx
|
||||
! enable password {# {{ en_passwd }} TODO: param needed #}
|
||||
{% endblock system_init %}
|
||||
!
|
||||
{% if DEVICE_METADATA['localhost']['type'] == "SpineChassisFrontendRouter" %}
|
||||
{% include "bgpd.conf.spine_chassis_frontend_router.j2" %}
|
||||
{% else%}
|
||||
{% endif %}
|
||||
!
|
||||
{% include "bgpd.conf.default.j2" %}
|
||||
{% endif %}
|
||||
!
|
||||
{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %}
|
||||
maximum-paths 64
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
{% endif %}
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
|
@ -1,3 +1,4 @@
|
||||
!
|
||||
{# VNET BGP Instance #}
|
||||
! Vnet BGP instance
|
||||
{% set interfaces_in_vnets = [] %}
|
||||
@ -59,70 +60,4 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} vrf {{ vnet_name }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endblock vnet_bgp_instance %}
|
||||
|
||||
{# default bgp #}
|
||||
{% block default_bgp_instance %}
|
||||
{% block bgp_init %}
|
||||
!
|
||||
! bgp multiple-instance
|
||||
!
|
||||
route-map FROM_BGP_SPEAKER_V4 permit 10
|
||||
!
|
||||
route-map TO_BGP_SPEAKER_V4 deny 10
|
||||
!
|
||||
router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
bgp log-neighbor-changes
|
||||
bgp bestpath as-path multipath-relax
|
||||
no bgp default ipv4-unicast
|
||||
bgp graceful-restart restart-time 240
|
||||
bgp graceful-restart
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE | pfx_filter %}
|
||||
{% if prefix | ipv4 and name == 'Loopback0' %}
|
||||
bgp router-id {{ prefix | ip }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{# advertise loopback #}
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE | pfx_filter %}
|
||||
{% if prefix | ipv4 and name == 'Loopback0' %}
|
||||
network {{ prefix | ip }}/32
|
||||
{% elif prefix | ipv6 and name == 'Loopback0' %}
|
||||
address-family ipv6
|
||||
network {{ prefix | ip }}/64
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock bgp_init %}
|
||||
{% block bgp_sessions %}
|
||||
{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %}
|
||||
{% if not bgp_session.has_key("local_addr") or bgp_session["local_addr"] not in interfaces_in_vnets %}
|
||||
{% if bgp_session['asn'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }}
|
||||
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
|
||||
{# set the bgp neighbor timers if they have not default values #}
|
||||
{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60)
|
||||
or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %}
|
||||
neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }}
|
||||
{% endif %}
|
||||
{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %}
|
||||
neighbor {{ neighbor_addr }} shutdown
|
||||
{% endif %}
|
||||
{% if bgp_session["asn"] != DEVICE_METADATA['localhost']['bgp_asn'] %}
|
||||
{% if neighbor_addr | ipv4 %}
|
||||
address-family ipv4 unicast
|
||||
neighbor {{ neighbor_addr }} allowas-in 1
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% else %}
|
||||
address-family l2vpn evpn
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
advertise-all-vni
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock bgp_sessions %}
|
||||
{% endblock default_bgp_instance %}
|
||||
|
30
dockers/docker-fpm-frr/bgpd.peer.conf.j2
Normal file
30
dockers/docker-fpm-frr/bgpd.peer.conf.j2
Normal file
@ -0,0 +1,30 @@
|
||||
{% block bgp_peer %}
|
||||
neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }}
|
||||
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
|
||||
{# set the bgp neighbor timers if they have not default values #}
|
||||
{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60)
|
||||
or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %}
|
||||
neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }}
|
||||
{% endif %}
|
||||
{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %}
|
||||
neighbor {{ neighbor_addr }} shutdown
|
||||
{% endif %}
|
||||
{% if neighbor_addr | ipv4 %}
|
||||
address-family ipv4
|
||||
neighbor {{ neighbor_addr }} peer-group PEER_V4
|
||||
{% elif neighbor_addr | ipv6 %}
|
||||
address-family ipv6
|
||||
{% if bgp_session['asn'] != DEVICE_METADATA['localhost']['bgp_asn'] %}
|
||||
neighbor {{ neighbor_addr }} route-map set-next-hop-global-v6 in
|
||||
{% endif %}
|
||||
neighbor {{ neighbor_addr }} peer-group PEER_V6
|
||||
{% endif %}
|
||||
{% if bgp_session['rrclient'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} route-reflector-client
|
||||
{% endif %}
|
||||
{% if bgp_session['nhopself'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} next-hop-self
|
||||
{% endif %}
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
exit-address-family
|
||||
{% endblock bgp_peer %}
|
12
dockers/docker-fpm-frr/daemons.common.conf.j2
Normal file
12
dockers/docker-fpm-frr/daemons.common.conf.j2
Normal file
@ -0,0 +1,12 @@
|
||||
!
|
||||
{% block sys_init %}
|
||||
hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
|
||||
password zebra
|
||||
enable password zebra
|
||||
{% endblock sys_init %}
|
||||
!
|
||||
{% block logging %}
|
||||
log syslog informational
|
||||
log facility local4
|
||||
{% endblock logging %}
|
||||
!
|
@ -6,205 +6,13 @@
|
||||
!
|
||||
{% endblock banner %}
|
||||
!
|
||||
{% block system_init %}
|
||||
hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
|
||||
password zebra
|
||||
log syslog informational
|
||||
log facility local4
|
||||
{% include "daemons.common.conf.j2" %}
|
||||
!
|
||||
agentx
|
||||
! enable password {# {{ en_passwd }} TODO: param needed #}
|
||||
{% endblock system_init %}
|
||||
!
|
||||
{% block interfaces %}
|
||||
! Enable link-detect (default disabled)
|
||||
{% for (name, prefix) in INTERFACE|pfx_filter %}
|
||||
interface {{ name }}
|
||||
link-detect
|
||||
{% include "zebra.interfaces.conf.j2" %}
|
||||
!
|
||||
{% endfor %}
|
||||
{% for pc in PORTCHANNEL %}
|
||||
interface {{ pc }}
|
||||
link-detect
|
||||
{% include "staticd.default_route.conf.j2" %}
|
||||
!
|
||||
{% endfor %}
|
||||
{% endblock interfaces %}
|
||||
!
|
||||
{% block default_route %}
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
|
||||
{% if prefix | ipv4 %}
|
||||
ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock default_route %}
|
||||
!
|
||||
{% block source_loopback %}
|
||||
{% set lo_ipv4_addrs = [] %}
|
||||
{% set lo_ipv6_addrs = [] %}
|
||||
{% if LOOPBACK_INTERFACE %}
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
||||
{% if name == 'Loopback0' %}
|
||||
{% if prefix | ipv6 %}
|
||||
{% if lo_ipv6_addrs.append(prefix) %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if lo_ipv4_addrs.append(prefix) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
! Set ip source to loopback for bgp learned routes
|
||||
route-map RM_SET_SRC permit 10
|
||||
set src {{ lo_ipv4_addrs[0] | ip }}
|
||||
!
|
||||
{% if lo_ipv6_addrs|length > 0 %}
|
||||
route-map RM_SET_SRC6 permit 10
|
||||
set src {{ lo_ipv6_addrs[0] | ip }}
|
||||
!
|
||||
{% endif %}
|
||||
ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
{% if lo_ipv6_addrs|length > 0 %}
|
||||
ipv6 protocol bgp route-map RM_SET_SRC6
|
||||
!
|
||||
{% endif %}
|
||||
{% endblock source_loopback %}
|
||||
!
|
||||
{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %}
|
||||
{% block bgp_init %}
|
||||
!
|
||||
! bgp multiple-instance
|
||||
!
|
||||
route-map FROM_BGP_SPEAKER_V4 permit 10
|
||||
!
|
||||
route-map TO_BGP_SPEAKER_V4 deny 10
|
||||
!
|
||||
router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
bgp log-neighbor-changes
|
||||
bgp bestpath as-path multipath-relax
|
||||
no bgp default ipv4-unicast
|
||||
{# Advertise graceful restart capability for ToR #}
|
||||
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
|
||||
bgp graceful-restart
|
||||
{% endif %}
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
||||
{% if prefix | ipv4 and name == 'Loopback0' %}
|
||||
bgp router-id {{ prefix | ip }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{# advertise loopback #}
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
||||
{% if prefix | ipv4 and name == 'Loopback0' %}
|
||||
network {{ prefix | ip }}/32
|
||||
{% elif prefix | ipv6 and name == 'Loopback0' %}
|
||||
address-family ipv6
|
||||
network {{ prefix | ip }}/64
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock bgp_init %}
|
||||
{% endif %}
|
||||
{% block vlan_advertisement %}
|
||||
{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %}
|
||||
{% if prefix | ipv4 %}
|
||||
network {{ prefix }}
|
||||
{% elif prefix | ipv6 %}
|
||||
address-family ipv6
|
||||
network {{ prefix }}
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock vlan_advertisement %}
|
||||
{% block bgp_sessions %}
|
||||
{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %}
|
||||
{% if bgp_session['asn'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }}
|
||||
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
|
||||
{# set the bgp neighbor timers if they have not default values #}
|
||||
{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60)
|
||||
or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %}
|
||||
neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }}
|
||||
{% endif %}
|
||||
{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %}
|
||||
neighbor {{ neighbor_addr }} shutdown
|
||||
{% endif %}
|
||||
{% if neighbor_addr | ipv4 %}
|
||||
address-family ipv4
|
||||
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
|
||||
neighbor {{ neighbor_addr }} allowas-in 1
|
||||
{% endif %}
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
|
||||
{% if bgp_session['rrclient'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} route-reflector-client
|
||||
{% endif %}
|
||||
{% if bgp_session['nhopself'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} next-hop-self
|
||||
{% endif %}
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% if neighbor_addr | ipv6 %}
|
||||
address-family ipv6
|
||||
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
|
||||
neighbor {{ neighbor_addr }} allowas-in 1
|
||||
{% endif %}
|
||||
neighbor {{ neighbor_addr }} activate
|
||||
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
|
||||
{% if bgp_session['rrclient'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} route-reflector-client
|
||||
{% endif %}
|
||||
{% if bgp_session['nhopself'] | int != 0 %}
|
||||
neighbor {{ neighbor_addr }} next-hop-self
|
||||
{% endif %}
|
||||
{% if bgp_session['asn'] != DEVICE_METADATA['localhost']['bgp_asn'] %}
|
||||
neighbor {{ neighbor_addr }} route-map set-next-hop-global-v6 in
|
||||
{% endif %}
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock bgp_sessions %}
|
||||
{% block bgp_peers_with_range %}
|
||||
{% if BGP_PEER_RANGE %}
|
||||
{% for bgp_peer in BGP_PEER_RANGE.values() %}
|
||||
neighbor {{ bgp_peer['name'] }} peer-group
|
||||
neighbor {{ bgp_peer['name'] }} passive
|
||||
neighbor {{ bgp_peer['name'] }} remote-as {{ deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']] }}
|
||||
neighbor {{ bgp_peer['name'] }} ebgp-multihop 255
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
||||
{% if name == 'Loopback1' %}
|
||||
neighbor {{ bgp_peer['name'] }} update-source {{ prefix | ip }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for ip_range in bgp_peer['ip_range'] %}
|
||||
bgp listen range {{ip_range}} peer-group {{ bgp_peer['name'] }}
|
||||
{% endfor %}
|
||||
address-family ipv4
|
||||
neighbor {{ bgp_peer['name'] }} activate
|
||||
neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound
|
||||
neighbor {{ bgp_peer['name'] }} route-map FROM_BGP_SPEAKER_V4 in
|
||||
neighbor {{ bgp_peer['name'] }} route-map TO_BGP_SPEAKER_V4 out
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
address-family ipv6
|
||||
neighbor {{ bgp_peer['name'] }} activate
|
||||
neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock bgp_peers_with_range %}
|
||||
!
|
||||
{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %}
|
||||
maximum-paths 64
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
|
||||
{% endif %}
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
{% include "bgpd.conf.default.j2" %}
|
||||
!
|
||||
|
@ -33,8 +33,6 @@ rm -f /var/run/rsyslogd.pid
|
||||
|
||||
supervisorctl start rsyslogd
|
||||
|
||||
supervisorctl start bgpcfgd
|
||||
|
||||
# Start Quagga processes
|
||||
supervisorctl start zebra
|
||||
supervisorctl start staticd
|
||||
@ -45,3 +43,5 @@ if [ "$CONFIG_TYPE" == "unified" ]; then
|
||||
fi
|
||||
|
||||
supervisorctl start fpmsyncd
|
||||
|
||||
supervisorctl start bgpcfgd
|
||||
|
@ -6,24 +6,7 @@
|
||||
!
|
||||
{% endblock banner %}
|
||||
!
|
||||
{% block sys_init %}
|
||||
hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
|
||||
password zebra
|
||||
enable password zebra
|
||||
{% endblock sys_init %}
|
||||
{% include "daemons.common.conf.j2" %}
|
||||
!
|
||||
{% block default_route %}
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
|
||||
{% if prefix | ipv4 %}
|
||||
ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock default_route %}
|
||||
{% include "staticd.default_route.conf.j2" %}
|
||||
!
|
||||
{% block logging %}
|
||||
log syslog informational
|
||||
log facility local4
|
||||
{% endblock logging %}
|
||||
!
|
||||
|
||||
|
10
dockers/docker-fpm-frr/staticd.default_route.conf.j2
Normal file
10
dockers/docker-fpm-frr/staticd.default_route.conf.j2
Normal file
@ -0,0 +1,10 @@
|
||||
!
|
||||
{% block default_route %}
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
|
||||
{% if prefix | ipv4 %}
|
||||
ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock default_route %}
|
||||
!
|
@ -6,74 +6,7 @@
|
||||
!
|
||||
{% endblock banner %}
|
||||
!
|
||||
{% block sys_init %}
|
||||
hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
|
||||
password zebra
|
||||
enable password zebra
|
||||
{% endblock sys_init %}
|
||||
{% include "daemons.common.conf.j2" %}
|
||||
!
|
||||
{% block vrf %}
|
||||
{% if VNET is defined %}
|
||||
{% for vnet_name, vnet_metadata in VNET.iteritems() %}
|
||||
vrf {{ vnet_name }}
|
||||
vni {{ vnet_metadata['vni'] }}
|
||||
{% include "zebra.interfaces.conf.j2" %}
|
||||
!
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock vrf %}
|
||||
!
|
||||
{% block interfaces %}
|
||||
! Enable link-detect (default disabled)
|
||||
{% for (name, prefix) in INTERFACE|pfx_filter %}
|
||||
interface {{ name }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
{% for pc in PORTCHANNEL %}
|
||||
interface {{ pc }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
{% endblock interfaces %}
|
||||
!
|
||||
{% block source_loopback %}
|
||||
{% set lo_ipv4_addrs = [] %}
|
||||
{% set lo_ipv6_addrs = [] %}
|
||||
{% if LOOPBACK_INTERFACE %}
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
||||
{% if name == 'Loopback0' %}
|
||||
{% if prefix | ipv6 %}
|
||||
{% if lo_ipv6_addrs.append(prefix) %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if lo_ipv4_addrs.append(prefix) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
! Set ip source to loopback for bgp learned routes
|
||||
{% if lo_ipv4_addrs|length > 0 -%}
|
||||
route-map RM_SET_SRC permit 10
|
||||
set src {{ lo_ipv4_addrs[0] | ip }}
|
||||
!
|
||||
{% endif %}
|
||||
{% if lo_ipv6_addrs|length > 0 %}
|
||||
route-map RM_SET_SRC6 permit 10
|
||||
set src {{ lo_ipv6_addrs[0] | ip }}
|
||||
!
|
||||
{% endif %}
|
||||
ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
{% if lo_ipv6_addrs|length > 0 %}
|
||||
ipv6 protocol bgp route-map RM_SET_SRC6
|
||||
!
|
||||
{% endif %}
|
||||
{% endblock source_loopback %}
|
||||
!
|
||||
{% block logging %}
|
||||
log syslog informational
|
||||
log facility local4
|
||||
{% endblock logging %}
|
||||
!
|
||||
|
||||
|
60
dockers/docker-fpm-frr/zebra.interfaces.conf.j2
Normal file
60
dockers/docker-fpm-frr/zebra.interfaces.conf.j2
Normal file
@ -0,0 +1,60 @@
|
||||
!
|
||||
{% block vrf %}
|
||||
{% if VNET is defined %}
|
||||
{% for vnet_name, vnet_metadata in VNET.iteritems() %}
|
||||
vrf {{ vnet_name }}
|
||||
vni {{ vnet_metadata['vni'] }}
|
||||
!
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock vrf %}
|
||||
!
|
||||
{% block interfaces %}
|
||||
! Enable link-detect (default disabled)
|
||||
{% for (name, prefix) in INTERFACE|pfx_filter %}
|
||||
interface {{ name }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
{% for pc in PORTCHANNEL %}
|
||||
interface {{ pc }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
{% endblock interfaces %}
|
||||
!
|
||||
{% block source_loopback %}
|
||||
{% set lo_ipv4_addrs = [] %}
|
||||
{% set lo_ipv6_addrs = [] %}
|
||||
{% if LOOPBACK_INTERFACE %}
|
||||
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
|
||||
{% if name == 'Loopback0' %}
|
||||
{% if prefix | ipv6 %}
|
||||
{% if lo_ipv6_addrs.append(prefix) %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if lo_ipv4_addrs.append(prefix) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
! Set ip source to loopback for bgp learned routes
|
||||
{% if lo_ipv4_addrs|length > 0 -%}
|
||||
route-map RM_SET_SRC permit 10
|
||||
set src {{ lo_ipv4_addrs[0] | ip }}
|
||||
!
|
||||
{% endif %}
|
||||
{% if lo_ipv6_addrs|length > 0 %}
|
||||
route-map RM_SET_SRC6 permit 10
|
||||
set src {{ lo_ipv6_addrs[0] | ip }}
|
||||
!
|
||||
{% endif %}
|
||||
ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
{% if lo_ipv6_addrs|length > 0 %}
|
||||
ipv6 protocol bgp route-map RM_SET_SRC6
|
||||
!
|
||||
{% endif %}
|
||||
{% endblock source_loopback %}
|
||||
!
|
@ -103,6 +103,14 @@ def pfx_filter(value):
|
||||
table[key] = val
|
||||
return table
|
||||
|
||||
def ip_network(value):
|
||||
""" Extract network for network prefix """
|
||||
try:
|
||||
r_v = netaddr.IPNetwork(value)
|
||||
except:
|
||||
return "Invalid ip address %s" % value
|
||||
return r_v.network
|
||||
|
||||
class FormatConverter:
|
||||
"""Convert config DB based schema to legacy minigraph based schema for backward capability.
|
||||
We will move to DB schema and remove this class when the config templates are modified.
|
||||
@ -265,6 +273,7 @@ def main():
|
||||
env.filters['ipv6'] = is_ipv6
|
||||
env.filters['unique_name'] = unique_name
|
||||
env.filters['pfx_filter'] = pfx_filter
|
||||
env.filters['ip_network'] = ip_network
|
||||
for attr in ['ip', 'network', 'prefixlen', 'netmask']:
|
||||
env.filters[attr] = partial(prefix_attr, attr)
|
||||
template = env.get_template(template_file)
|
||||
|
@ -4,12 +4,18 @@
|
||||
! file: bgpd.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname switch-t0
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
agentx
|
||||
! enable password !
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
! bgp multiple-instance
|
||||
!
|
||||
@ -18,7 +24,7 @@ route-map FROM_BGP_SPEAKER_V4 permit 10
|
||||
route-map TO_BGP_SPEAKER_V4 deny 10
|
||||
!
|
||||
ip prefix-list PL_LoopbackV4 permit 10.1.0.32/32
|
||||
ipv6 prefix-list PL_LoopbackV6 permit fc00:1::32/64
|
||||
ipv6 prefix-list PL_LoopbackV6 permit fc00:1::/64
|
||||
!
|
||||
!
|
||||
route-map TO_BGP_PEER_V4 permit 100
|
||||
@ -29,6 +35,13 @@ route-map FROM_BGPMON_V4 deny 10
|
||||
!
|
||||
route-map TO_BGPMON_V4 permit 10
|
||||
!
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend 65100
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
router bgp 65100
|
||||
bgp log-neighbor-changes
|
||||
bgp bestpath as-path multipath-relax
|
||||
@ -42,81 +55,23 @@ router bgp 65100
|
||||
network fc00:1::32/64
|
||||
exit-address-family
|
||||
network 192.168.0.1/27
|
||||
neighbor 10.0.0.57 remote-as 64600
|
||||
neighbor 10.0.0.57 description ARISTA01T1
|
||||
neighbor 10.0.0.57 route-map TO_BGP_PEER_V4 out
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.57 allowas-in 1
|
||||
neighbor 10.0.0.57 activate
|
||||
neighbor 10.0.0.57 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor 10.0.0.59 remote-as 64600
|
||||
neighbor 10.0.0.59 description ARISTA02T1
|
||||
neighbor 10.0.0.59 route-map TO_BGP_PEER_V4 out
|
||||
address-family ipv6
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor PEER_V4 peer-group
|
||||
neighbor PEER_V6 peer-group
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.59 allowas-in 1
|
||||
neighbor 10.0.0.59 activate
|
||||
neighbor 10.0.0.59 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
neighbor PEER_V4 allowas-in 1
|
||||
neighbor PEER_V4 soft-reconfiguration inbound
|
||||
neighbor PEER_V4 route-map TO_BGP_PEER_V4 out
|
||||
exit-address-family
|
||||
neighbor 10.0.0.61 remote-as 64600
|
||||
neighbor 10.0.0.61 description ARISTA03T1
|
||||
neighbor 10.0.0.61 route-map TO_BGP_PEER_V4 out
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.61 allowas-in 1
|
||||
neighbor 10.0.0.61 activate
|
||||
neighbor 10.0.0.61 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor 10.0.0.63 remote-as 64600
|
||||
neighbor 10.0.0.63 description ARISTA04T1
|
||||
neighbor 10.0.0.63 route-map TO_BGP_PEER_V4 out
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.63 allowas-in 1
|
||||
neighbor 10.0.0.63 activate
|
||||
neighbor 10.0.0.63 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::7a remote-as 64600
|
||||
neighbor fc00::7a description ARISTA03T1
|
||||
address-family ipv6
|
||||
neighbor fc00::7a allowas-in 1
|
||||
neighbor fc00::7a activate
|
||||
neighbor fc00::7a soft-reconfiguration inbound
|
||||
neighbor fc00::7a route-map set-next-hop-global-v6 in
|
||||
neighbor fc00::7a route-map TO_BGP_PEER_V6 out
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::7e remote-as 64600
|
||||
neighbor fc00::7e description ARISTA04T1
|
||||
address-family ipv6
|
||||
neighbor fc00::7e allowas-in 1
|
||||
neighbor fc00::7e activate
|
||||
neighbor fc00::7e soft-reconfiguration inbound
|
||||
neighbor fc00::7e route-map set-next-hop-global-v6 in
|
||||
neighbor fc00::7e route-map TO_BGP_PEER_V6 out
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::72 remote-as 64600
|
||||
neighbor fc00::72 description ARISTA01T1
|
||||
address-family ipv6
|
||||
neighbor fc00::72 allowas-in 1
|
||||
neighbor fc00::72 activate
|
||||
neighbor fc00::72 soft-reconfiguration inbound
|
||||
neighbor fc00::72 route-map set-next-hop-global-v6 in
|
||||
neighbor fc00::72 route-map TO_BGP_PEER_V6 out
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::76 remote-as 64600
|
||||
neighbor fc00::76 description ARISTA02T1
|
||||
address-family ipv6
|
||||
neighbor fc00::76 allowas-in 1
|
||||
neighbor fc00::76 activate
|
||||
neighbor fc00::76 soft-reconfiguration inbound
|
||||
neighbor fc00::76 route-map set-next-hop-global-v6 in
|
||||
neighbor fc00::76 route-map TO_BGP_PEER_V6 out
|
||||
maximum-paths 64
|
||||
neighbor PEER_V6 allowas-in 1
|
||||
neighbor PEER_V6 soft-reconfiguration inbound
|
||||
neighbor PEER_V6 route-map TO_BGP_PEER_V6 out
|
||||
exit-address-family
|
||||
neighbor BGPMON_V4 peer-group
|
||||
neighbor BGPMON_V4 update-source 10.1.0.32
|
||||
@ -129,11 +84,3 @@ router bgp 65100
|
||||
neighbor 10.20.30.40 description BGPMonitor
|
||||
neighbor 10.20.30.40 activate
|
||||
!!
|
||||
maximum-paths 64
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend 65100
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
|
@ -4,12 +4,18 @@
|
||||
! file: frr.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname switch-t0
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
agentx
|
||||
! enable password !
|
||||
!
|
||||
!
|
||||
!
|
||||
! Enable link-detect (default disabled)
|
||||
interface PortChannel01
|
||||
link-detect
|
||||
@ -24,9 +30,6 @@ interface PortChannel04
|
||||
link-detect
|
||||
!
|
||||
!
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
ip route 0.0.0.0/0 10.0.0.1 200
|
||||
!
|
||||
! Set ip source to loopback for bgp learned routes
|
||||
route-map RM_SET_SRC permit 10
|
||||
set src 10.1.0.32
|
||||
@ -39,6 +42,11 @@ ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
ipv6 protocol bgp route-map RM_SET_SRC6
|
||||
!
|
||||
!!
|
||||
!
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
ip route 0.0.0.0/0 10.0.0.1 200
|
||||
!!
|
||||
!
|
||||
!
|
||||
! bgp multiple-instance
|
||||
@ -47,91 +55,64 @@ route-map FROM_BGP_SPEAKER_V4 permit 10
|
||||
!
|
||||
route-map TO_BGP_SPEAKER_V4 deny 10
|
||||
!
|
||||
ip prefix-list PL_LoopbackV4 permit 10.1.0.32/32
|
||||
ipv6 prefix-list PL_LoopbackV6 permit fc00:1::/64
|
||||
!
|
||||
!
|
||||
route-map TO_BGP_PEER_V4 permit 100
|
||||
!
|
||||
route-map TO_BGP_PEER_V6 permit 100
|
||||
!
|
||||
route-map FROM_BGPMON_V4 deny 10
|
||||
!
|
||||
route-map TO_BGPMON_V4 permit 10
|
||||
!
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend 65100
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
router bgp 65100
|
||||
bgp log-neighbor-changes
|
||||
bgp bestpath as-path multipath-relax
|
||||
no bgp default ipv4-unicast
|
||||
bgp graceful-restart restart-time 240
|
||||
bgp graceful-restart
|
||||
bgp graceful-restart preserve-fw-state
|
||||
bgp router-id 10.1.0.32
|
||||
network 10.1.0.32/32
|
||||
address-family ipv6
|
||||
network fc00:1::32/64
|
||||
exit-address-family
|
||||
network 192.168.0.1/27
|
||||
neighbor 10.0.0.57 remote-as 64600
|
||||
neighbor 10.0.0.57 description ARISTA01T1
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.57 allowas-in 1
|
||||
neighbor 10.0.0.57 activate
|
||||
neighbor 10.0.0.57 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor 10.0.0.59 remote-as 64600
|
||||
neighbor 10.0.0.59 description ARISTA02T1
|
||||
address-family ipv6
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor PEER_V4 peer-group
|
||||
neighbor PEER_V6 peer-group
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.59 allowas-in 1
|
||||
neighbor 10.0.0.59 activate
|
||||
neighbor 10.0.0.59 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
neighbor PEER_V4 allowas-in 1
|
||||
neighbor PEER_V4 soft-reconfiguration inbound
|
||||
neighbor PEER_V4 route-map TO_BGP_PEER_V4 out
|
||||
exit-address-family
|
||||
neighbor 10.0.0.61 remote-as 64600
|
||||
neighbor 10.0.0.61 description ARISTA03T1
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.61 allowas-in 1
|
||||
neighbor 10.0.0.61 activate
|
||||
neighbor 10.0.0.61 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor 10.0.0.63 remote-as 64600
|
||||
neighbor 10.0.0.63 description ARISTA04T1
|
||||
address-family ipv4
|
||||
neighbor 10.0.0.63 allowas-in 1
|
||||
neighbor 10.0.0.63 activate
|
||||
neighbor 10.0.0.63 soft-reconfiguration inbound
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::7a remote-as 64600
|
||||
neighbor fc00::7a description ARISTA03T1
|
||||
address-family ipv6
|
||||
neighbor fc00::7a allowas-in 1
|
||||
neighbor fc00::7a activate
|
||||
neighbor fc00::7a soft-reconfiguration inbound
|
||||
neighbor fc00::7a route-map set-next-hop-global-v6 in
|
||||
maximum-paths 64
|
||||
neighbor PEER_V6 allowas-in 1
|
||||
neighbor PEER_V6 soft-reconfiguration inbound
|
||||
neighbor PEER_V6 route-map TO_BGP_PEER_V6 out
|
||||
exit-address-family
|
||||
neighbor fc00::7e remote-as 64600
|
||||
neighbor fc00::7e description ARISTA04T1
|
||||
address-family ipv6
|
||||
neighbor fc00::7e allowas-in 1
|
||||
neighbor fc00::7e activate
|
||||
neighbor fc00::7e soft-reconfiguration inbound
|
||||
neighbor fc00::7e route-map set-next-hop-global-v6 in
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::72 remote-as 64600
|
||||
neighbor fc00::72 description ARISTA01T1
|
||||
address-family ipv6
|
||||
neighbor fc00::72 allowas-in 1
|
||||
neighbor fc00::72 activate
|
||||
neighbor fc00::72 soft-reconfiguration inbound
|
||||
neighbor fc00::72 route-map set-next-hop-global-v6 in
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor fc00::76 remote-as 64600
|
||||
neighbor fc00::76 description ARISTA02T1
|
||||
address-family ipv6
|
||||
neighbor fc00::76 allowas-in 1
|
||||
neighbor fc00::76 activate
|
||||
neighbor fc00::76 soft-reconfiguration inbound
|
||||
neighbor fc00::76 route-map set-next-hop-global-v6 in
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
!
|
||||
maximum-paths 64
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend 65100
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
neighbor BGPMON_V4 peer-group
|
||||
neighbor BGPMON_V4 update-source 10.1.0.32
|
||||
neighbor BGPMON_V4 route-map FROM_BGPMON_V4 in
|
||||
neighbor BGPMON_V4 route-map TO_BGPMON_V4 out
|
||||
neighbor BGPMON_V4 send-community
|
||||
neighbor BGPMON_V4 maximum-prefix 1
|
||||
neighbor 10.20.30.40 remote-as 65100
|
||||
neighbor 10.20.30.40 peer-group BGPMON_V4
|
||||
neighbor 10.20.30.40 description BGPMonitor
|
||||
neighbor 10.20.30.40 activate
|
||||
!!
|
||||
|
@ -4,14 +4,15 @@
|
||||
! file: staticd.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname switch-t0
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
ip route 0.0.0.0/0 10.0.0.1 200
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
!
|
||||
|
||||
! set static default route to mgmt gateway as a backup to learned default
|
||||
ip route 0.0.0.0/0 10.0.0.1 200
|
||||
!!
|
||||
|
@ -4,12 +4,17 @@
|
||||
! file: bgpd.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname SpineFront01
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
agentx
|
||||
! enable password !
|
||||
!
|
||||
!
|
||||
! Vnet BGP instance
|
||||
router bgp 4000 vrf VnetFE
|
||||
no bgp default ipv4-unicast
|
||||
@ -30,7 +35,8 @@ router bgp 4000 vrf VnetFE
|
||||
address-family l2vpn evpn
|
||||
advertise ipv4 unicast
|
||||
exit-address-family
|
||||
|
||||
!!
|
||||
!
|
||||
!
|
||||
! bgp multiple-instance
|
||||
!
|
||||
@ -38,6 +44,20 @@ route-map FROM_BGP_SPEAKER_V4 permit 10
|
||||
!
|
||||
route-map TO_BGP_SPEAKER_V4 deny 10
|
||||
!
|
||||
ip prefix-list PL_LoopbackV4 permit 4.0.0.0/32
|
||||
!
|
||||
!
|
||||
route-map TO_BGP_PEER_V4 permit 100
|
||||
!
|
||||
route-map TO_BGP_PEER_V6 permit 100
|
||||
!
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend 4000
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
router bgp 4000
|
||||
bgp log-neighbor-changes
|
||||
bgp bestpath as-path multipath-relax
|
||||
@ -46,37 +66,20 @@ router bgp 4000
|
||||
bgp graceful-restart
|
||||
bgp router-id 4.0.0.0
|
||||
network 4.0.0.0/32
|
||||
neighbor 4.0.0.1 remote-as 4000
|
||||
neighbor 4.0.0.1 description SpineFront02
|
||||
neighbor 4.0.0.1 timers 3 10
|
||||
address-family l2vpn evpn
|
||||
neighbor 4.0.0.1 activate
|
||||
advertise-all-vni
|
||||
exit-address-family
|
||||
neighbor 172.16.0.2 remote-as 5000
|
||||
neighbor 172.16.0.2 description SpineBack01
|
||||
neighbor 172.16.0.2 timers 3 10
|
||||
address-family ipv4 unicast
|
||||
neighbor 172.16.0.2 allowas-in 1
|
||||
neighbor 172.16.0.2 activate
|
||||
neighbor 172.16.0.2 soft-reconfiguration inbound
|
||||
address-family ipv4
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
neighbor 172.16.0.10 remote-as 5000
|
||||
neighbor 172.16.0.10 description SpineBack02
|
||||
neighbor 172.16.0.10 timers 3 10
|
||||
address-family ipv4 unicast
|
||||
neighbor 172.16.0.10 allowas-in 1
|
||||
neighbor 172.16.0.10 activate
|
||||
neighbor 172.16.0.10 soft-reconfiguration inbound
|
||||
address-family ipv6
|
||||
maximum-paths 64
|
||||
exit-address-family
|
||||
!
|
||||
maximum-paths 64
|
||||
!
|
||||
route-map ISOLATE permit 10
|
||||
set as-path prepend 4000
|
||||
!
|
||||
route-map set-next-hop-global-v6 permit 10
|
||||
set ipv6 next-hop prefer-global
|
||||
!
|
||||
neighbor PEER_V4 peer-group
|
||||
neighbor PEER_V6 peer-group
|
||||
address-family ipv4
|
||||
neighbor PEER_V4 soft-reconfiguration inbound
|
||||
neighbor PEER_V4 route-map TO_BGP_PEER_V4 out
|
||||
exit-address-family
|
||||
address-family ipv6
|
||||
neighbor PEER_V6 soft-reconfiguration inbound
|
||||
neighbor PEER_V6 route-map TO_BGP_PEER_V6 out
|
||||
exit-address-family
|
||||
!!
|
||||
|
@ -4,10 +4,15 @@
|
||||
! file: zebra.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname SpineFront01
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
!
|
||||
vrf VnetFE
|
||||
vni 9000
|
||||
!
|
||||
@ -29,8 +34,4 @@ route-map RM_SET_SRC permit 10
|
||||
!
|
||||
ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!
|
||||
|
||||
!!
|
||||
|
@ -4,10 +4,15 @@
|
||||
! file: zebra.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname SpineFront01
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
!
|
||||
vrf VnetFE
|
||||
vni 8000
|
||||
!
|
||||
@ -29,8 +34,4 @@ route-map RM_SET_SRC permit 10
|
||||
!
|
||||
ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!
|
||||
|
||||
!!
|
||||
|
@ -4,10 +4,15 @@
|
||||
! file: zebra.conf
|
||||
!
|
||||
!
|
||||
!
|
||||
hostname switch-t0
|
||||
password zebra
|
||||
enable password zebra
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!!
|
||||
!
|
||||
!
|
||||
! Enable link-detect (default disabled)
|
||||
interface PortChannel01
|
||||
@ -35,8 +40,4 @@ ip protocol bgp route-map RM_SET_SRC
|
||||
!
|
||||
ipv6 protocol bgp route-map RM_SET_SRC6
|
||||
!
|
||||
!
|
||||
log syslog informational
|
||||
log facility local4
|
||||
!
|
||||
|
||||
!!
|
||||
|
62
src/sonic-config-engine/tests/test_frr.py
Normal file
62
src/sonic-config-engine/tests/test_frr.py
Normal file
@ -0,0 +1,62 @@
|
||||
from unittest import TestCase
|
||||
import subprocess
|
||||
import os
|
||||
import filecmp
|
||||
|
||||
|
||||
class TestCfgGen(TestCase):
|
||||
def setUp(self):
|
||||
self.test_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen')
|
||||
self.t0_minigraph = os.path.join(self.test_dir, 't0-sample-graph.xml')
|
||||
self.t0_port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini')
|
||||
self.output_file = os.path.join(self.test_dir, 'output')
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
os.remove(self.output_file)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def run_script(self, argument, check_stderr=False):
|
||||
# print '\n Running sonic-cfggen ' + argument
|
||||
if check_stderr:
|
||||
output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True)
|
||||
else:
|
||||
output = subprocess.check_output(self.script_file + ' ' + argument, shell=True)
|
||||
|
||||
linecount = output.strip().count('\n')
|
||||
if linecount <= 0:
|
||||
print ' Output: ' + output.strip()
|
||||
else:
|
||||
print ' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))
|
||||
return output
|
||||
|
||||
def run_diff(self, file1, file2):
|
||||
return subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True)
|
||||
|
||||
def run_case(self, template, target):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', template)
|
||||
cmd = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(cmd)
|
||||
|
||||
original_filename = os.path.join(self.test_dir, 'sample_output', target)
|
||||
r = filecmp.cmp(original_filename, self.output_file)
|
||||
diff_output = self.run_diff(original_filename, self.output_file) if not r else ""
|
||||
|
||||
return r, "Diff:\n" + diff_output
|
||||
|
||||
|
||||
def test_config_frr(self):
|
||||
self.assertTrue(*self.run_case('frr.conf.j2', 'frr.conf'))
|
||||
|
||||
def test_bgpd_frr(self):
|
||||
self.assertTrue(*self.run_case('bgpd.conf.j2', 'bgpd_frr.conf'))
|
||||
|
||||
def test_zebra_frr(self):
|
||||
self.assertTrue(*self.run_case('zebra.conf.j2', 'zebra_frr.conf'))
|
||||
|
||||
def test_staticd_frr(self):
|
||||
self.assertTrue(*self.run_case('staticd.conf.j2', 'staticd_frr.conf'))
|
||||
|
@ -77,34 +77,6 @@ class TestJ2Files(TestCase):
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'zebra_quagga.conf'), self.output_file))
|
||||
|
||||
def test_config_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'frr.conf.j2')
|
||||
argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'frr.conf'), self.output_file))
|
||||
|
||||
|
||||
def test_bgpd_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'bgpd.conf.j2')
|
||||
argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
original_filename = os.path.join(self.test_dir, 'sample_output', 'bgpd_frr.conf')
|
||||
r = filecmp.cmp(original_filename, self.output_file)
|
||||
diff_output = self.run_diff(original_filename, self.output_file) if not r else ""
|
||||
self.assertTrue(r, "Diff:\n" + diff_output)
|
||||
|
||||
def test_zebra_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'zebra.conf.j2')
|
||||
argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'zebra_frr.conf'), self.output_file))
|
||||
|
||||
def test_staticd_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'staticd.conf.j2')
|
||||
argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'staticd_frr.conf'), self.output_file))
|
||||
|
||||
def test_ipinip(self):
|
||||
ipinip_file = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ipinip.json.j2')
|
||||
argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + ipinip_file + ' > ' + self.output_file
|
||||
|
@ -16,42 +16,39 @@ class TestJ2FilesT2ChassisFe(TestCase):
|
||||
self.t2_chassis_fe_port_config = os.path.join(self.test_dir, 't2-chassis-fe-port-config.ini')
|
||||
self.output_file = os.path.join(self.test_dir, 'output')
|
||||
|
||||
def run_script(self, argument):
|
||||
print 'CMD: sonic-cfggen ' + argument
|
||||
return subprocess.check_output(self.script_file + ' ' + argument, shell=True)
|
||||
|
||||
# Test zebra.conf in FRR docker for a T2 chassis frontend (fe)
|
||||
def test_t2_chassis_fe_zebra_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'zebra.conf.j2')
|
||||
argument = '-m ' + self.t2_chassis_fe_minigraph + ' -p ' + self.t2_chassis_fe_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 't2-chassis-fe-zebra.conf'), self.output_file))
|
||||
|
||||
# Test zebra.conf in FRR docker for a T2 chassis frontend (fe) switch with port channel interfaces
|
||||
def test_t2_chassis_fe_pc_zebra_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'zebra.conf.j2')
|
||||
argument = '-m ' + self.t2_chassis_fe_pc_minigraph + ' -p ' + self.t2_chassis_fe_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 't2-chassis-fe-pc-zebra.conf'), self.output_file))
|
||||
|
||||
# Test zebra.conf in FRR docker for a T2 chassis frontend (fe) switch with specified VNI
|
||||
def test_t2_chassis_fe_vni_zebra_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'zebra.conf.j2')
|
||||
argument = '-m ' + self.t2_chassis_fe_vni_minigraph + ' -p ' + self.t2_chassis_fe_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 't2-chassis-fe-vni-zebra.conf'), self.output_file))
|
||||
|
||||
# Test bgpd.conf in FRR docker for a T2 chassis frontend (fe)
|
||||
def test_t2_chassis_frontend_bgpd_frr(self):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'bgpd.conf.j2')
|
||||
argument = '-m ' + self.t2_chassis_fe_minigraph + ' -p ' + self.t2_chassis_fe_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(argument)
|
||||
self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 't2-chassis-fe-bgpd.conf'), self.output_file))
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
os.remove(self.output_file)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def run_script(self, argument):
|
||||
print 'CMD: sonic-cfggen ' + argument
|
||||
return subprocess.check_output(self.script_file + ' ' + argument, shell=True)
|
||||
|
||||
def run_diff(self, file1, file2):
|
||||
return subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True)
|
||||
|
||||
def run_case(self, minigraph, template, target):
|
||||
conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', template)
|
||||
cmd = '-m ' + minigraph + ' -p ' + self.t2_chassis_fe_port_config + ' -t ' + conf_template + ' > ' + self.output_file
|
||||
self.run_script(cmd)
|
||||
|
||||
original_filename = os.path.join(self.test_dir, 'sample_output', target)
|
||||
r = filecmp.cmp(original_filename, self.output_file)
|
||||
diff_output = self.run_diff(original_filename, self.output_file) if not r else ""
|
||||
|
||||
return r, "Diff:\n" + diff_output
|
||||
|
||||
# Test zebra.conf in FRR docker for a T2 chassis frontend (fe)
|
||||
def test_t2_chassis_fe_zebra_frr(self):
|
||||
self.assertTrue(*self.run_case(self.t2_chassis_fe_minigraph, 'zebra.conf.j2', 't2-chassis-fe-zebra.conf'))
|
||||
|
||||
# Test zebra.conf in FRR docker for a T2 chassis frontend (fe) switch with specified VNI
|
||||
def test_t2_chassis_fe_vni_zebra_frr(self):
|
||||
self.assertTrue(*self.run_case(self.t2_chassis_fe_vni_minigraph, 'zebra.conf.j2', 't2-chassis-fe-vni-zebra.conf'))
|
||||
|
||||
# Test bgpd.conf in FRR docker for a T2 chassis frontend (fe)
|
||||
def test_t2_chassis_frontend_bgpd_frr(self):
|
||||
self.assertTrue(*self.run_case(self.t2_chassis_fe_minigraph, 'bgpd.conf.j2', 't2-chassis-fe-bgpd.conf'))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user