[frrcfgd] introduce frrcfgd to manage frr config when frr_mgmt_framework_config is true (#5142)

- Support for non-template based FRR configurations (BGP, route-map, OSPF, static route..etc) using config DB schema.
- Support for save & restore - Jinja template based config-DB data read and apply to FRR during startup

**- How I did it**

- add frrcfgd service
- when frr_mgmg_framework_config is set, frrcfgd starts in bgp container
- when user changed the BGP or other related table entries in config DB, frrcfgd will run corresponding VTYSH commands to program on FRR.
- add jinja template to generate FRR config file to be used by FRR daemons while bgp container restarted

**- How to verify it**
1. Add/delete data on config DB and then run VTYSH "show running-config" command to check if FRR configuration changed.
1. Restart bgp container and check if generated FRR config file is correct and run VTYSH "show running-config" command to check if FRR configuration is consistent with attributes in config DB

Co-authored-by: Zhenhong Zhao <zhenhong.zhao@dell.com>
This commit is contained in:
Zhenhong Zhao 2021-01-24 17:57:03 -08:00 committed by Guohan Lu
parent 7e2b7553bc
commit 154a6ab6c5
42 changed files with 5976 additions and 14 deletions

View File

@ -54,7 +54,6 @@ COPY ["TSA", "/usr/bin/TSA"]
COPY ["TSB", "/usr/bin/TSB"]
COPY ["TSC", "/usr/bin/TSC"]
COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
COPY ["critical_processes", "/etc/supervisor"]
COPY ["bgpd.sh", "/usr/bin/"]
RUN chmod a+x /usr/bin/TSA && \
chmod a+x /usr/bin/TSB && \

View File

@ -1,5 +0,0 @@
program:zebra
program:staticd
program:bgpd
program:fpmsyncd
program:bgpcfgd

View File

@ -6,16 +6,25 @@ mkdir -p /etc/supervisor/conf.d
CFGGEN_PARAMS=" \
-d \
-y /etc/sonic/constants.yml \
-t /usr/share/sonic/templates/supervisord/frr_vars.j2 \
-t /usr/share/sonic/templates/frr_vars.j2 \
-t /usr/share/sonic/templates/supervisord/supervisord.conf.j2,/etc/supervisor/conf.d/supervisord.conf \
-t /usr/share/sonic/templates/bgpd/bgpd.conf.j2,/etc/frr/bgpd.conf \
-t /usr/share/sonic/templates/bgpd/gen_bgpd.conf.j2,/etc/frr/bgpd.conf \
-t /usr/share/sonic/templates/supervisord/critical_processes.j2,/etc/supervisor/critical_processes \
-t /usr/share/sonic/templates/zebra/zebra.conf.j2,/etc/frr/zebra.conf \
-t /usr/share/sonic/templates/staticd/staticd.conf.j2,/etc/frr/staticd.conf \
-t /usr/share/sonic/templates/frr.conf.j2,/etc/frr/frr.conf \
-t /usr/share/sonic/templates/staticd/gen_staticd.conf.j2,/etc/frr/staticd.conf \
-t /usr/share/sonic/templates/gen_frr.conf.j2,/etc/frr/frr.conf \
-t /usr/share/sonic/templates/isolate.j2,/usr/sbin/bgp-isolate \
-t /usr/share/sonic/templates/unisolate.j2,/usr/sbin/bgp-unisolate \
-t /usr/local/sonic/frrcfgd/bfdd.conf.j2,/etc/frr/bfdd.conf \
-t /usr/local/sonic/frrcfgd/ospfd.conf.j2,/etc/frr/ospfd.conf \
"
CONFIG_TYPE=$(sonic-cfggen $CFGGEN_PARAMS)
FRR_VARS=$(sonic-cfggen $CFGGEN_PARAMS)
MGMT_FRAMEWORK_CONFIG=$(echo $FRR_VARS | jq -r '.frr_mgmt_framework_config')
CONFIG_TYPE=$(echo $FRR_VARS | jq -r '.docker_routing_config_mode')
if [ -z "$MGMT_FRAMEWORK_CONFIG" ] || [ "$MGMT_FRAMEWORK_CONFIG" == "false" ]; then
rm /etc/frr/bfdd.conf /etc/frr/ospfd.conf
fi
update_default_gw()
{
@ -52,7 +61,8 @@ if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then
rm -f /etc/frr/frr.conf
elif [ "$CONFIG_TYPE" == "unified" ]; then
echo "service integrated-vtysh-config" > /etc/frr/vtysh.conf
rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf /etc/frr/staticd.conf
rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf /etc/frr/staticd.conf \
/etc/frr/bfdd.conf /etc/frr/ospfd.conf /etc/frr/pimd.conf
fi
chown -R frr:frr /etc/frr/

View File

@ -0,0 +1,5 @@
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
{% include "/usr/local/sonic/frrcfgd/bgpd.conf.j2" %}
{% else %}
{% include "/usr/share/sonic/templates/bgpd/bgpd.conf.j2" %}
{% endif %}

View File

@ -1 +1,14 @@
{{ DEVICE_METADATA["localhost"]["docker_routing_config_mode"] }}
{
"frr_mgmt_framework_config":
{% if "frr_mgmt_framework_config" in DEVICE_METADATA["localhost"].keys() %}
"{{ DEVICE_METADATA["localhost"]["frr_mgmt_framework_config"] }}"
{% else %}
""
{% endif %},
"docker_routing_config_mode":
{% if "docker_routing_config_mode" in DEVICE_METADATA["localhost"].keys() %}
"{{ DEVICE_METADATA["localhost"]["docker_routing_config_mode"] }}"
{% else %}
""
{% endif %}
}

View File

@ -0,0 +1,5 @@
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
{% include "/usr/local/sonic/frrcfgd/frr.conf.j2" %}
{% else %}
{% include "/usr/share/sonic/templates/frr.conf.j2" %}
{% endif %}

View File

@ -0,0 +1,5 @@
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
{% include "/usr/local/sonic/frrcfgd/staticd.conf.j2" %}
{% else %}
{% include "/usr/share/sonic/templates/staticd/staticd.conf.j2" %}
{% endif %}

View File

@ -0,0 +1,12 @@
program:zebra
program:staticd
program:bgpd
program:fpmsyncd
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
program:bfdd
program:ospfd
program:pimd
program:frrcfgd
{% else %}
program:bgpcfgd
{% endif %}

View File

@ -50,6 +50,20 @@ stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=zebra:running
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
[program:bfdd]
command=/usr/lib/frr/bfdd -A 127.0.0.1
priority=4
stopsignal=KILL
autostart=false
autorestart=false
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=zebra:running
{% endif %}
[program:bgpd]
command=/usr/bin/bgpd.sh -A 127.0.0.1 -M snmp
priority=5
@ -62,6 +76,32 @@ stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=zebra:running
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
[program:ospfd]
command=/usr/lib/frr/ospfd -A 127.0.0.1 -M snmp
priority=5
stopsignal=KILL
autostart=false
autorestart=false
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=zebra:running
[program:pimd]
command=/usr/lib/frr/pimd -A 127.0.0.1
priority=5
stopsignal=KILL
autostart=false
autorestart=false
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=zebra:running
{% endif %}
[program:fpmsyncd]
command=fpmsyncd
priority=6
@ -73,8 +113,13 @@ stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=bgpd:running
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
[program:frrcfgd]
command=/usr/local/bin/frrcfgd
{% else %}
[program:bgpcfgd]
command=/usr/local/bin/bgpcfgd
{% endif %}
priority=6
autostart=false
autorestart=false

View File

@ -5,7 +5,7 @@ DOCKER_FPM_FRR = $(DOCKER_FPM_FRR_STEM).gz
DOCKER_FPM_FRR_DBG = $(DOCKER_FPM_FRR_STEM)-$(DBG_IMAGE_MARK).gz
$(DOCKER_FPM_FRR)_PATH = $(DOCKERS_PATH)/$(DOCKER_FPM_FRR_STEM)
$(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD)
$(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD) $(SONIC_FRR_MGMT_FRAMEWORK)
$(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(FRR_SNMP) $(SWSS) $(LIBYANG1)
$(DOCKER_FPM_FRR)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS)

View File

@ -0,0 +1,8 @@
SPATH := $($(SONIC_FRR_MGMT_FRAMEWORK)_SRC_PATH)
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-frr-mgmt-framework.mk rules/sonic-frr-mgmt-framework.dep
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
DEP_FILES += $(shell git ls-files $(SPATH))
$(SONIC_FRR_MGMT_FRAMEWORK)_CACHE_MODE := GIT_CONTENT_SHA
$(SONIC_FRR_MGMT_FRAMEWORK)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
$(SONIC_FRR_MGMT_FRAMEWORK)_DEP_FILES := $(DEP_FILES)

View File

@ -0,0 +1,13 @@
# sonic-frr-mgmt-framework package
SONIC_FRR_MGMT_FRAMEWORK = sonic_frr_mgmt_framework-1.0-py3-none-any.whl
$(SONIC_FRR_MGMT_FRAMEWORK)_SRC_PATH = $(SRC_PATH)/sonic-frr-mgmt-framework
# These dependencies are only needed because they are dependencies
# of sonic-config-engine and frrcfgd explicitly calls sonic-cfggen
# as part of its unit tests.
# TODO: Refactor unit tests so that these dependencies are not needed
$(SONIC_FRR_MGMT_FRAMEWORK)_DEPENDS += $(SONIC_CONFIG_ENGINE_PY3)
$(SONIC_FRR_MGMT_FRAMEWORK)_DEBS_DEPENDS += $(PYTHON_SWSSCOMMON)
$(SONIC_FRR_MGMT_FRAMEWORK)_PYTHON_VERSION = 3
SONIC_PYTHON_WHEELS += $(SONIC_FRR_MGMT_FRAMEWORK)

12
src/sonic-frr-mgmt-framework/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
.eggs/
build/
dist/
*.egg-info/
frrcfgd/*.pyc
tests/*.pyc
tests/__pycache__/
.idea
.coverage
frrcfgd/__pycache__/
venv
tests/.coverage*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
[pytest]
addopts = --cov=frrcfgd --cov-report term

View File

@ -0,0 +1,5 @@
[aliases]
test=pytest
[tool:pytest]
addopts = --verbose
python_files = tests/*.py

View File

@ -0,0 +1,51 @@
import setuptools
setuptools.setup(
name = 'sonic-frr-mgmt-framework',
version = '1.0',
description = 'Utility to dynamically configuration FRR based on config DB data update event',
url = 'https://github.com/Azure/sonic-buildimage',
packages = setuptools.find_packages(),
entry_points = {
'console_scripts': [
'frrcfgd = frrcfgd.frrcfgd:main',
]
},
install_requires = [
'jinja2>=2.10',
'netaddr==0.8.0',
'pyyaml==5.3.1',
'zipp==1.2.0', # importlib-resources needs zipp and seems to have a bug where it will try to import too new of a version for Python 2
],
setup_requires = [
'pytest-runner',
'wheel'
],
tests_require = [
'pytest',
'pytest-cov',
'sonic-config-engine'
],
data_files = [('sonic/frrcfgd', ['templates/bgpd/bgpd.conf.j2',
'templates/bgpd/bgpd.conf.db.j2',
'templates/bgpd/bgpd.conf.db.route_map.j2',
'templates/bgpd/bgpd.conf.db.pref_list.j2',
'templates/bgpd/bgpd.conf.db.nbr_or_peer.j2',
'templates/bgpd/bgpd.conf.db.nbr_af.j2',
'templates/bgpd/bgpd.conf.db.comm_list.j2',
'templates/bgpd/bgpd.conf.db.addr_family.j2',
'templates/bgpd/bgpd.conf.db.addr_family.evpn.j2',
'templates/bfdd/bfdd.conf.j2',
'templates/ospfd/ospfd.conf.j2',
'templates/ospfd/ospfd.conf.db.area.j2',
'templates/ospfd/ospfd.conf.db.comm_list.j2',
'templates/ospfd/ospfd.conf.db.distributeroute.j2',
'templates/ospfd/ospfd.conf.db.interface.j2',
'templates/ospfd/ospfd.conf.db.policyrange.j2',
'templates/ospfd/ospfd.conf.db.vlink.j2',
'templates/staticd/staticd.conf.j2',
'templates/staticd/staticd.db.conf.j2',
'templates/staticd/staticd.db.default_route.conf.j2',
'templates/frr/frr.conf.j2'])
]
)

View File

@ -0,0 +1,91 @@
!
{% block banner %}
! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
! generated by templates/frr/bfd.conf.j2 with config DB data
! file: bfd.conf
!
{% endblock banner %}
!
{% block bfd_shop_peers %}
{% if BFD_PEER_SINGLE_HOP %}
bfd
{% for (peer_key, peer_info) in BFD_PEER_SINGLE_HOP.items() %}
{% set peer_args = '' %}
{% if peer_key[0] != 'null' %}
{% set peer_args = peer_args~' '~'peer'~' '~peer_key[0] %}
{% endif %}
{% if peer_key[1] != 'null' %}
{% set peer_args = peer_args~' '~'interface'~' '~peer_key[1] %}
{% endif %}
{% if peer_key[2] != 'null' %}
{% set peer_args = peer_args~' '~'vrf'~' '~peer_key[2] %}
{% endif %}
{% if peer_key[3] != 'null' %}
{% set peer_args = peer_args~' '~'local-address'~' '~peer_key[3] %}
{% endif %}
{{ peer_args }}
{# set the bfd peer timers #}
{% if (peer_info['desired-minimum-tx-interval'] is defined and peer_info['desired-minimum-tx-interval'] | int != 300) %}
transmit-interval {{ peer_info['desired-minimum-tx-interval'] }}
{% endif %}
{% if (peer_info['required-minimum-receive'] is defined and peer_info['required-minimum-receive'] | int != 300) %}
receive-interval {{ peer_info['required-minimum-receive'] }}
{% endif %}
{% if (peer_info['detection-multiplier'] is defined and peer_info['detection-multiplier'] | int != 3) %}
detect-multiplier {{ peer_info['detection-multiplier'] }}
{% endif %}
{% if (peer_info['echo-active'] is defined and peer_info['echo-active'] != 'false') %}
echo-mode
{% endif %}
{% if (peer_info['desired-minimum-echo-receive'] is defined and peer_info['desired-minimum-echo-receive'] | int != 50) %}
echo-interval {{ peer_info['desired-minimum-echo-receive'] }}
{% endif %}
{% if (peer_info['enabled'] is defined and peer_info['enabled'] == 'true') %}
no shutdown
{% else %}
shutdown
{% endif %}
!
{% endfor %}
!
{% endif %}
{% endblock bfd_shop_peers%}
{% block bfd_mhop_peers %}
{% if BFD_PEER_MULTI_HOP %}
bfd
{% for (peer_key, peer_info) in BFD_PEER_MULTI_HOP.items() %}
{% set peer_args = '' %}
{% if peer_key[0] != 'null' %}
{% set peer_args = peer_args~' '~'peer'~' '~peer_key[0] %}
{% endif %}
{% if peer_key[1] != 'null' %}
{% set peer_args = peer_args~' '~'interface'~' '~peer_key[1] %}
{% endif %}
{% if peer_key[2] != 'null' %}
{% set peer_args = peer_args~' '~'vrf'~' '~peer_key[2] %}
{% endif %}
{% if peer_key[3] != 'null' %}
{% set peer_args = peer_args~' '~'local-address'~' '~peer_key[3] %}
{% endif %}
{% set peer_args = peer_args~' '~'multihop' %}
{{ peer_args }}
{# set the bfd peer timers #}
{% if (peer_info['desired-minimum-tx-interval'] is defined and peer_info['desired-minimum-tx-interval'] | int != 300) %}
transmit-interval {{ peer_info['desired-minimum-tx-interval'] }}
{% endif %}
{% if (peer_info['required-minimum-receive'] is defined and peer_info['required-minimum-receive'] | int != 300) %}
receive-interval {{ peer_info['required-minimum-receive'] }}
{% endif %}
{% if (peer_info['detection-multiplier'] is defined and peer_info['detection-multiplier'] | int != 3) %}
detect-multiplier {{ peer_info['detection-multiplier'] }}
{% endif %}
{% if (peer_info['enabled'] is defined and peer_info['enabled'] == 'true') %}
no shutdown
{% else %}
shutdown
{% endif %}
!
{% endfor %}
!
{% endif %}
{% endblock bfd_mhop_peers%}

View File

@ -0,0 +1,78 @@
{% if 'advertise-all-vni' in af_val and af_val['advertise-all-vni'] == 'true' %}
advertise-all-vni
{% endif %}
{% if 'autort' in af_val %}
autort {{af_val['autort']}}
{% endif %}
{% if 'advertise-default-gw' in af_val and af_val['advertise-default-gw'] == 'true' %}
advertise-default-gw
{% endif %}
{% if 'dad-enabled' in af_val and 'dad-max-moves' in af_val and 'dad-time' in af_val %}
dup-addr-detection max-moves {{af_val['dad-max-moves']}} time {{af_val['dad-time']}}
{% endif %}
{% if 'dad-freeze' in af_val %}
dup-addr-detection freeze {{af_val['dad-freeze']}}
{% endif %}
{% if 'advertise-ipv4-unicast' in af_val and af_val['advertise-ipv4-unicast'] == 'true' %}
advertise ipv4 unicast
{% endif %}
{% if 'advertise-ipv6-unicast' in af_val and af_val['advertise-ipv6-unicast'] == 'true' %}
advertise ipv6 unicast
{% endif %}
{% if 'default-originate-ipv4' in af_val and af_val['default-originate-ipv4'] == 'true' %}
default-originate ipv4
{% endif %}
{% if 'default-originate-ipv6' in af_val and af_val['default-originate-ipv6'] == 'true' %}
default-originate ipv6
{% endif %}
{% if 'route-distinguisher' in af_val %}
rd {{af_val['route-distinguisher']}}
{% endif %}
{% if 'import-rts' in af_val %}
{% for irt in af_val['import-rts'] %}
route-target import {{irt}}
{% endfor %}
{% endif %}
{% if 'export-rts' in af_val %}
{% for irt in af_val['export-rts'] %}
route-target export {{irt}}
{% endfor %}
{% endif %}
{% if BGP_GLOBALS_EVPN_RT is defined and BGP_GLOBALS_EVPN_RT|length > 0 %}
{% for evpn_rt_key, evpn_rt_val in BGP_GLOBALS_EVPN_RT.items() %}
{% if vrf == evpn_rt_key[0] %}
route-target {{evpn_rt_val['route-target-type']}} {{evpn_rt_key[2]}}
{% endif %}
{% endfor %}
{% endif %}
{% if BGP_GLOBALS_EVPN_VNI is defined and BGP_GLOBALS_EVPN_VNI|length > 0 %}
{% for vni_key, vni_val in BGP_GLOBALS_EVPN_VNI.items() %}
{% if vrf == vni_key[0] %}
vni {{vni_key[2]}}
{% if 'route-distinguisher' in vni_val %}
rd {{vni_val['route-distinguisher']}}
{% endif %}
{% if 'import-rts' in vni_val %}
{% for irt in vni_val['import-rts'] %}
route-target import {{irt}}
{% endfor %}
{% endif %}
{% if 'export-rts' in vni_val %}
{% for irt in vni_val['export-rts'] %}
route-target export {{irt}}
{% endfor %}
{% endif %}
{% if BGP_GLOBALS_EVPN_VNI_RT is defined and BGP_GLOBALS_EVPN_VNI_RT|length > 0 %}
{% for vni_rt_key, vni_rt_val in BGP_GLOBALS_EVPN_VNI_RT.items() %}
{% if vrf == vni_rt_key[0] and vni_key[2] == vni_rt_key[2] %}
route-target {{vni_rt_val['route-target-type']}} {{vni_rt_key[3]}}
{% endif %}
{% endfor %}
{% endif %}
{% if 'advertise-default-gw' in vni_val and vni_val['advertise-default-gw'] == 'true' %}
advertise-default-gw
{% endif %}
exit-vni
{% endif %}
{% endfor %}
{% endif %}

View File

@ -0,0 +1,143 @@
{# -----------------------------------------------------------------------------------------#}
{# this is invoked with the "vrf" variable set #}
{# -----------------------------------------------------------------------------------------#}
{# -------address-family --------------------------- #}
{% if (BGP_GLOBALS_AF is defined and BGP_GLOBALS_AF|length > 0) or
(BGP_GLOBALS_AF_NETWORK is defined and BGP_GLOBALS_AF_NETWORK|length > 0) or
(BGP_GLOBALS_AF_AGGREGATE_ADDR is defined and BGP_GLOBALS_AF_AGGREGATE_ADDR|length > 0) or
(ROUTE_REDISTRIBUTE is defined and ROUTE_REDISTRIBUTE|length > 0) or
(BGP_PEER_GROUP_AF is defined and BGP_PEER_GROUP_AF|length > 0) or
(BGP_NEIGHBOR_AF is defined and BGP_NEIGHBOR_AF|length > 0) %}
{% set af_str_map = { 'ipv4_unicast': 'ipv4', 'ipv6_unicast':'ipv6', 'l2vpn_evpn':'l2vpn'} %}
{% set safi_str_map = { 'ipv4_unicast': 'unicast', 'ipv6_unicast':'unicast', 'l2vpn_evpn':'evpn'} %}
{% for af, af_str in af_str_map|dictsort %}
!
address-family {{af_str}} {{safi_str_map[af]}}
{% if BGP_GLOBALS_AF is defined and BGP_GLOBALS_AF|length > 0 %}
{% for af_key, af_val in BGP_GLOBALS_AF.items() %}
{% if vrf == af_key[0] and af == af_key[1] %}
{% if 'ebgp_route_distance' in af_val and 'ibgp_route_distance' in af_val and 'local_route_distance' in af_val %}
distance bgp {{af_val['ebgp_route_distance']}} {{af_val['ibgp_route_distance']}} {{af_val['local_route_distance']}}
{% endif %}
{% if 'import_vrf' in af_val %}
import vrf {{af_val['import_vrf']}}
{% endif %}
{% if 'import_vrf_route_map' in af_val %}
import vrf route-map {{af_val['import_vrf_route_map']}}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# ------- network-prefix --------------------------- #}
{% if BGP_GLOBALS_AF_NETWORK is defined and BGP_GLOBALS_AF_NETWORK|length > 0 %}
{% for af_nw_key, af_nw_val in BGP_GLOBALS_AF_NETWORK.items() %}
{% if vrf == af_nw_key[0] and af == af_nw_key[1] %}
{% set af_nw_ns = namespace(nw_end = '') %}
{% if 'backdoor' in af_nw_val and af_nw_val['backdoor'] == 'true' %}
{% set af_nw_ns.nw_end = 'backdoor ' %}
{% endif %}
{% if 'policy' in af_nw_val %}
{% set af_nw_ns.nw_end = af_nw_ns.nw_end + 'route-map ' + af_nw_val['policy'] %}
{% endif %}
network {{af_nw_key[2]}} {{af_nw_ns.nw_end}}
{% endif %}
{% endfor %}
{% endif %}
{# ------- network-prefix end --------------------------- #}
{# ------- aggregate-prefix -Start--------------------------- #}
{% if BGP_GLOBALS_AF_AGGREGATE_ADDR is defined and BGP_GLOBALS_AF_AGGREGATE_ADDR|length > 0 %}
{% for af_ag_key, af_ag_val in BGP_GLOBALS_AF_AGGREGATE_ADDR.items() %}
{% set af_ag_ns = namespace(ag_end = '') %}
{% if vrf == af_ag_key[0] and af == af_ag_key[1] %}
{% if 'as_set' in af_ag_val and af_ag_val['as_set'] == 'true' %}
{% set af_ag_ns.ag_end = 'as-set ' %}
{% endif %}
{% if 'summary_only' in af_ag_val and af_ag_val['summary_only'] == 'true' %}
{% set af_ag_ns.ag_end = af_ag_ns.ag_end + 'summary-only' %}
{% endif %}
aggregate-address {{af_ag_key[2]}} {{af_ag_ns.ag_end}}
{% endif %}
{% endfor %}
{% endif %}
{# ------- aggregate-prefix - End --------------------------- #}
{# ------- redistribute - Start --------------------------- #}
{% if ROUTE_REDISTRIBUTE is defined and ROUTE_REDISTRIBUTE|length > 0 %}
{% for rr_key, rr_val in ROUTE_REDISTRIBUTE.items() %}
{% if vrf == rr_key[0] and af_str == rr_key[3] %}
{% if 'route_map' in rr_val %}
{% for rmap in rr_val['route_map'] %}
redistribute {{rr_key[1]}} route-map {{rmap}}
{% endfor %}
{% else %}
redistribute {{rr_key[1]}}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# ------- redistribute - End ----------------------------- #}
{# ------- peer-group af--------------------------- #}
{% if BGP_PEER_GROUP_AF is defined and BGP_PEER_GROUP_AF|length > 0 %}
{% for n_af_key, n_af_val in BGP_PEER_GROUP_AF.items() %}
{% if vrf == n_af_key[0] and af == n_af_key[2] %}
{% set nbr_name = n_af_key[1] %}
{% include "bgpd.conf.db.nbr_af.j2" %}
{% endif %}
{% endfor %}
{% endif %}
{# ------- peer-group af end --------------------------- #}
{# ------- neighbor af--------------------------- #}
{% if BGP_NEIGHBOR_AF is defined and BGP_NEIGHBOR_AF|length > 0 %}
{% for n_af_key, n_af_val in BGP_NEIGHBOR_AF.items() %}
{% if vrf == n_af_key[0] and af == n_af_key[2] %}
{% set nbr_name = n_af_key[1] %}
{% include "bgpd.conf.db.nbr_af.j2" %}
{% endif %}
{% endfor %}
{% endif %}
{# ------- neighbor af end --------------------------- #}
{% if BGP_GLOBALS_AF is defined and BGP_GLOBALS_AF|length > 0 %}
{% for af_key, af_val in BGP_GLOBALS_AF.items() %}
{% if vrf == af_key[0] and af == af_key[1] %}
{# -------bgp dampen - start--------------------------- #}
{% if 'route_flap_dampen' in af_val and af_val['route_flap_dampen'] == 'true' %}
{% set ns = namespace(route_dampen = '') %}
{% if 'route_flap_dampen_half_life' in af_val %}
{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_half_life'] + ' ' %}
{% if 'route_flap_dampen_reuse_threshold' in af_val %}
{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_reuse_threshold'] + ' ' %}
{% if 'route_flap_dampen_suppress_threshold' in af_val %}
{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_suppress_threshold'] + ' ' %}
{% if 'route_flap_dampen_max_suppress' in af_val %}
{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_max_suppress'] + ' ' %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
bgp dampening {{ns.route_dampen}}
{% endif %}
{# -------bgp dampen - end --------------------------- #}
{% if 'max_ebgp_paths' in af_val %}
maximum-paths {{af_val['max_ebgp_paths']}}
{% endif %}
{% if 'max_ibgp_paths' in af_val %}
{% set ns = namespace(max_ibgp = af_val['max_ibgp_paths']) %}
{% if 'ibgp_equal_cluster_length' in af_val and af_val['ibgp_equal_cluster_length'] == 'true' %}
{% set ns.max_ibgp = ns.max_ibgp + ' equal-cluster-length' %}
{% endif %}
maximum-paths ibgp {{ns.max_ibgp}}
{% endif %}
{% if 'route_download_filter' in af_val %}
table-map {{af_val['route_download_filter']}}
{% endif %}
{# -------bgp evpn - start --------------------------- #}
{% if af == 'l2vpn_evpn' %}
{% include "bgpd.conf.db.addr_family.evpn.j2" %}
{% endif %}
{# -------bgp evpn - end --------------------------- #}
{% endif %}
{% endfor %}
{% endif %}
exit-address-family
{% endfor %}
{% endif %}
{# -------address-family end --------------------------- #}

View File

@ -0,0 +1,54 @@
{# ------------------------------------------------------------------------------------ #}
{% if (COMMUNITY_SET is defined and COMMUNITY_SET|length > 0) or
(EXTENDED_COMMUNITY_SET is defined and EXTENDED_COMMUNITY_SET|length >0) %}
!
{% endif %}
{# ------------------------------------------------------------------------------------ #}
{% if COMMUNITY_SET is defined and COMMUNITY_SET|length > 0 %}
{% for cm_key, cm_val in COMMUNITY_SET.items() %}
{% if 'set_type' in cm_val and 'match_action' in cm_val and 'community_member' in cm_val %}
{% if cm_val['match_action']|lower == 'all' %}
{% set ns = namespace(cm_list = '') %}
{% for cm in cm_val['community_member'] %}
{% set ns.cm_list = ns.cm_list + cm + ' ' %}
{% endfor %}
bgp community-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{ns.cm_list}}
{% elif cm_val['match_action']|lower == 'any' %}
{% for cm in cm_val['community_member'] %}
bgp community-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{cm}}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# ------------------------------------------------------------------------------------ #}
{% if EXTENDED_COMMUNITY_SET is defined and EXTENDED_COMMUNITY_SET|length > 0 %}
{% for cm_key, cm_val in EXTENDED_COMMUNITY_SET.items() %}
{% if 'set_type' in cm_val and 'match_action' in cm_val and 'community_member' in cm_val %}
{% if cm_val['match_action']|lower == 'all' %}
{% set ns = namespace(cm_list = '') %}
{% for cm in cm_val['community_member'] %}
{% if 'route-target' in cm %}
{% set ns.cm_list = ns.cm_list + 'rt ' + cm[13:] + ' ' %}
{% elif 'route-origin' in cm %}
{% set ns.cm_list = ns.cm_list + 'soo ' + cm[13:] + ' ' %}
{% else %}
{% set ns.cm_list = ns.cm_list + cm + ' ' %}
{% endif %}
{% endfor %}
bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{ns.cm_list}}
{% elif cm_val['match_action']|lower == 'any' %}
{% for cm in cm_val['community_member'] %}
{% if 'route-target' in cm %}
bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit rt {{cm[13:]}}
{% elif 'route-origin' in cm %}
bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit soo {{cm[13:]}}
{% else %}
bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{cm}}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# ------------------------------------------------------------------------------------ #}

View File

@ -0,0 +1,204 @@
! template: bgpd/bgpd.conf.db.j2
!
! BGP configuration using config DB BGP instance tables
!
{# ------------------------------------------------------------------------------------ #}
{% include "bgpd.conf.db.pref_list.j2" %}
{# ------------------------------------------------------------------------------------ #}
{# ------------------------------------------------------------------------------------ #}
{% include "bgpd.conf.db.route_map.j2" %}
{# ------------------------------------------------------------------------------------ #}
{% if AS_PATH_SET is defined and AS_PATH_SET|length > 0 %}
!
{% for key, val in AS_PATH_SET.items() %}
{% if 'as_path_set_member' in val %}
{% for path in val['as_path_set_member'] %}
bgp as-path access-list {{key}} permit {{path}}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{# ------------------------------------------------------------------------------------ #}
{% include "bgpd.conf.db.comm_list.j2" %}
{# ------------------------------------------------------------------------------------ #}
{% if BGP_GLOBALS is defined and BGP_GLOBALS|length > 0 %}
{% for vrf, bgp_sess in BGP_GLOBALS.items() %}
{% if 'local_asn' in bgp_sess %}
!
{% if vrf == 'default' %}
router bgp {{ bgp_sess['local_asn']}}
{% else %}
router bgp {{ bgp_sess['local_asn']}} vrf {{ vrf }}
{% endif %}
{% if 'fast_external_failover' in bgp_sess and bgp_sess['fast_external_failover'] == 'false' %}
no bgp fast-external-failover
{% endif %}
{% if 'router_id' in bgp_sess %}
bgp router-id {{bgp_sess['router_id']}}
{% endif %}
{% if 'log_nbr_state_changes' in bgp_sess and bgp_sess['log_nbr_state_changes'] == 'true' %}
bgp log-neighbor-changes
{% endif %}
{% if 'always_compare_med' in bgp_sess and bgp_sess['always_compare_med'] == 'true' %}
bgp always-compare-med
{% endif %}
{# --------------------------bgp default - start -------------------------------------- #}
{% if 'default_ipv4_unicast' in bgp_sess and bgp_sess['default_ipv4_unicast'] == 'true' %}
bgp default ipv4-unicast
{% else %}
no bgp default ipv4-unicast
{% endif %}
{% if 'default_local_preference' in bgp_sess %}
bgp default local-preference {{bgp_sess['default_local_preference']}}
{% endif %}
{% if 'default_show_hostname' in bgp_sess and bgp_sess['default_show_hostname'] == 'true' %}
bgp default show-hostname
{% endif %}
{% if 'default_shutdown' in bgp_sess and bgp_sess['default_shutdown'] == 'true' %}
bgp default shutdown
{% endif %}
{% if 'default_subgroup_pkt_queue_max' in bgp_sess %}
bgp default subgroup-pkt-queue-max {{bgp_sess['default_subgroup_pkt_queue_max']}}
{% endif %}
{# --------------------------bgp default - end ---------------------------------------- #}
{% if 'rr_clnt_to_clnt_reflection' in bgp_sess and bgp_sess['rr_clnt_to_clnt_reflection'] == 'false' %}
no bgp client-to-client reflection
{% endif %}
{% if 'rr_cluster_id' in bgp_sess %}
bgp cluster-id {{bgp_sess['rr_cluster_id']}}
{% endif %}
{% if 'disable_ebgp_connected_rt_check' in bgp_sess and bgp_sess['disable_ebgp_connected_rt_check'] == 'true' %}
bgp disable-ebgp-connected-route-check
{% endif %}
{% if 'deterministic_med' in bgp_sess and bgp_sess['deterministic_med'] == 'true' %}
bgp deterministic-med
{% endif %}
{% if 'max_delay' in bgp_sess %}
{% set ns = namespace(max_delay = '') %}
{% set ns.max_delay = ns.max_delay + bgp_sess['max_delay'] %}
{% if 'establish_wait' in bgp_sess %}
{% set ns.max_delay = ns.max_delay + ' ' + bgp_sess['establish_wait'] %}
{% endif %}
update-delay {{ns.max_delay}}
{% endif %}
{% if 'max_med_time' in bgp_sess %}
{% set ns = namespace(max_med = '') %}
{% set ns.max_med = ns.max_med + bgp_sess['max_med_time'] %}
{% if 'max_med_val' in bgp_sess %}
{% set ns.max_med = ns.max_med + ' ' + bgp_sess['max_med_val'] %}
{% endif %}
bgp max-med on-startup {{ns.max_med}}
{% endif %}
{% if 'max_med_admin' in bgp_sess %}
{% set adm_ns = namespace(admin_val = '') %}
{% if 'max_med_admin_val' in bgp_sess %}
{% set adm_ns.admin_val = adm_ns.admin_val + ' ' + bgp_sess['max_med_admin_val'] %}
{% endif %}
bgp max-med administrative {{adm_ns.admin_val}}
{% endif %}
{% if 'read_quanta' in bgp_sess %}
read-quanta {{bgp_sess['read_quanta']}}
{% endif %}
{% if 'write_quanta' in bgp_sess %}
write-quanta {{bgp_sess['write_quanta']}}
{% endif %}
{% if 'coalesce_time' in bgp_sess %}
coalesce-time {{bgp_sess['coalesce_time']}}
{% endif %}
{# --------------------------bgp graceful-restart - start ----------------------------- #}
{% if 'gr_stale_routes_time' in bgp_sess %}
bgp graceful-restart stalepath-time {{bgp_sess['gr_stale_routes_time']}}
{% endif %}
{% if 'gr_restart_time' in bgp_sess %}
bgp graceful-restart restart-time {{bgp_sess['gr_restart_time']}}
{% endif %}
{% if 'graceful_restart_enable' in bgp_sess and bgp_sess['graceful_restart_enable'] == 'true' %}
bgp graceful-restart
{% endif %}
{% if 'graceful_shutdown' in bgp_sess and bgp_sess['graceful_shutdown'] == 'true' %}
bgp graceful-shutdown
{% endif %}
{% if 'gr_preserve_fw_state' in bgp_sess and bgp_sess['gr_preserve_fw_state'] == 'true' %}
bgp graceful-restart preserve-fw-state
{% endif %}
{# --------------------------bgp graceful-restart - end ----------------------------- #}
{# --------------------------bgp bestpath as-path - start ----------------------------- #}
{% if 'ignore_as_path_length' in bgp_sess %}
bgp bestpath as-path ignore
{% endif %}
{% if 'compare_confed_as_path' in bgp_sess and bgp_sess['compare_confed_as_path'] == 'true' %}
bgp bestpath as-path confed
{% endif %}
{% if 'load_balance_mp_relax' in bgp_sess and bgp_sess['load_balance_mp_relax'] == 'true' %}
{% set mp_ns = namespace(mp_val = '') %}
{% if 'as_path_mp_as_set' in bgp_sess and bgp_sess['as_path_mp_as_set'] == 'true' %}
{% set mp_ns.mp_val = mp_ns.mp_val + 'as-set' %}
{% elif 'as_path_mp_as_set' in bgp_sess and bgp_sess['as_path_mp_as_set'] == 'false' %}
{% set mp_ns.mp_val = mp_ns.mp_val + 'no-as-set' %}
{% endif %}
bgp bestpath as-path multipath-relax {{mp_ns.mp_val}}
{% endif %}
{# --------------------------bgp bestpath as-path - end ----------------------------- #}
{% if 'rr_allow_out_policy' in bgp_sess and bgp_sess['rr_allow_out_policy'] == 'true' %}
bgp route-reflector allow-outbound-policy
{% endif %}
{% if 'external_compare_router_id' in bgp_sess %}
bgp bestpath compare-routerid
{% endif %}
{% if 'med_confed' in bgp_sess and bgp_sess['med_confed'] == 'true' %}
bgp bestpath med confed
{% endif %}
{% if 'med_missing_as_worst' in bgp_sess and bgp_sess['med_missing_as_worst'] == 'true' %}
bgp bestpath med confed missing-as-worst
{% endif %}
{% if 'network_import_check' in bgp_sess and bgp_sess['network_import_check'] == 'true' %}
bgp network import-check
{% endif %}
{# -------globals end --------------------------- #}
{# -------peer-group --------------------------- #}
{% if BGP_PEER_GROUP is defined and BGP_PEER_GROUP|length > 0 %}
{% for peer_group, nbr_or_peer in BGP_PEER_GROUP.items() %}
{% if vrf == peer_group[0] %}
{% set name_or_ip = peer_group[1] %}
{% set nbr_or_peer_type = 'peer-group' %}
{% include "bgpd.conf.db.nbr_or_peer.j2" %}
{% endif %}
{% endfor %}
{% endif %}
{# -------peer-group end --------------------------- #}
{# -------neighbor --------------------------- #}
{% if BGP_NEIGHBOR is defined and BGP_NEIGHBOR|length > 0 %}
{% for nbr_addr, nbr_or_peer in BGP_NEIGHBOR.items() %}
{% if nbr_addr is not string and nbr_addr|length > 1 %}
{% if vrf == nbr_addr[0] %}
{% set name_or_ip = nbr_addr[1] %}
{% set nbr_or_peer_type = 'neighbor' %}
{% include "bgpd.conf.db.nbr_or_peer.j2" %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# -------neighbor end --------------------------- #}
{% if 'max_dynamic_neighbors' in bgp_sess %}
bgp listen limit {{bgp_sess['max_dynamic_neighbors']}}
{% endif %}
{% if 'route_map_process_delay' in bgp_sess %}
bgp route-map delay-timer {{bgp_sess['route_map_process_delay']}}
{% endif %}
{# -------listen-prefix --------------------------- #}
{% if BGP_GLOBALS_LISTEN_PREFIX is defined and BGP_GLOBALS_LISTEN_PREFIX|length > 0 %}
{% for lpfx, lpfx_val in BGP_GLOBALS_LISTEN_PREFIX.items() %}
{% if vrf == lpfx[0] %}
{% if 'peer_group' in lpfx_val %}
bgp listen range {{lpfx[1]}} peer-group {{lpfx_val['peer_group']}}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# -------listen-prefix end --------------------------- #}
{# -------address-family --------------------------- #}
{% include "bgpd.conf.db.addr_family.j2" %}
{# -------address-family --------------------------- #}
{% endif %}
{% endfor %}
{% endif %}

View File

@ -0,0 +1,150 @@
{# ------------------------------------------------------------ #}
{# this is called with the "vrf" and "address-family matched #}
{# ------------------------------------------------------------ #}
{% if 'admin_status' in n_af_val %}
{% if n_af_val['admin_status'] == 'true' %}
neighbor {{nbr_name}} activate
{% else %}
no neighbor {{nbr_name}} activate
{% endif %}
{% endif %}
{% if 'tx_add_paths' in n_af_val %}
{% if n_af_val['tx_add_paths'] == 'tx_all_paths' %}
neighbor {{nbr_name}} addpath-tx-all-paths
{% elif n_af_val['tx_add_paths'] == 'tx_best_path_per_as' %}
neighbor {{nbr_name}} addpath-tx-bestpath-per-AS
{% endif %}
{% endif %}
{% if 'nhself' in n_af_val and n_af_val['nhself'] == 'true' %}
{% if 'nexthop_self_force' in n_af_val and n_af_val['nexthop_self_force'] == 'true' %}
neighbor {{nbr_name}} next-hop-self force
{% else %}
neighbor {{nbr_name}} next-hop-self
{% endif %}
{% endif %}
{% if 'remove_private_as_enabled' in n_af_val and n_af_val['remove_private_as_enabled'] == 'true' %}
{% set ns = namespace(rpas_str='') %}
{% if 'remove_private_as_all' in n_af_val and n_af_val['remove_private_as_all'] == 'true' %}
{% set ns.rpas_str = ns.rpas_str + ' all' %}
{% endif %}
{% if 'replace_private_as' in n_af_val and n_af_val['replace_private_as'] == 'true' %}
{% set ns.rpas_str = ns.rpas_str + ' replace-AS' %}
{% endif %}
neighbor {{nbr_name}} remove-private-AS{{ns.rpas_str}}
{% endif %}
{% if 'send_community' in n_af_val %}
{% if n_af_val['send_community'] == 'standard' %}
no neighbor {{nbr_name}} send-community extended
no neighbor {{nbr_name}} send-community large
{% elif n_af_val['send_community'] == 'extended' %}
no neighbor {{nbr_name}} send-community
no neighbor {{nbr_name}} send-community large
{% elif n_af_val['send_community'] == 'large' %}
no neighbor {{nbr_name}} send-community
no neighbor {{nbr_name}} send-community extended
{% elif n_af_val['send_community'] == 'both' %}
no neighbor {{nbr_name}} send-community large
{% elif n_af_val['send_community'] == 'none' %}
no neighbor {{nbr_name}} send-community all
{% endif %}
{% endif %}
{% if 'as_override' in n_af_val and n_af_val['as_override'] == 'true' %}
neighbor {{nbr_name}} as-override
{% endif %}
{% if 'send_default_route' in n_af_val and n_af_val['send_default_route'] == 'true' %}
{% if 'default_rmap' in n_af_val %}
neighbor {{nbr_name}} default-originate route-map {{n_af_val['default_rmap']}}
{% else %}
neighbor {{nbr_name}} default-originate
{% endif %}
{% endif %}
{% if 'rrclient' in n_af_val and n_af_val['rrclient'] == 'true' %}
neighbor {{nbr_name}} route-reflector-client
{% endif %}
{% if 'soft_reconfiguration_in' in n_af_val and n_af_val['soft_reconfiguration_in'] == 'true' %}
neighbor {{nbr_name}} soft-reconfiguration inbound
{% endif %}
{# ------- maximum-prefix --------------------------- #}
{% if 'max_prefix_limit' in n_af_val %}
{% set ns = namespace(mpfx_str='maximum-prefix ' + n_af_val['max_prefix_limit']) %}
{% if 'max_prefix_warning_threshold' in n_af_val %}
{% set ns.mpfx_str = ns.mpfx_str + ' ' + n_af_val['max_prefix_warning_threshold'] %}
{% endif %}
{% if 'max_prefix_restart_interval' in n_af_val %}
{% set ns.mpfx_str = ns.mpfx_str + ' restart ' + n_af_val['max_prefix_restart_interval'] %}
{% elif 'max_prefix_warning_only' in n_af_val and n_af_val['max_prefix_warning_only'] == 'true' %}
{% set ns.mpfx_str = ns.mpfx_str + ' warning-only' %}
{% endif %}
neighbor {{nbr_name}} {{ns.mpfx_str}}
{% endif %}
{# ------- maximum-prefix end --------------------------- #}
{% if 'route_server_client' in n_af_val and n_af_val['route_server_client'] == 'true' %}
neighbor {{nbr_name}} route-server-client
{% endif %}
{# ------- allow-as --------------------------- #}
{% if 'allow_as_in' in n_af_val and n_af_val['allow_as_in'] == 'true' %}
{% if 'allow_as_origin' in n_af_val and n_af_val['allow_as_origin'] == 'true' %}
neighbor {{nbr_name}} allowas-in origin
{% elif 'allow_as_count' in n_af_val %}
neighbor {{nbr_name}} allowas-in {{n_af_val['allow_as_count']}}
{% else %}
neighbor {{nbr_name}} allowas-in
{% endif %}
{% endif %}
{# ------- allow-as end --------------------------- #}
{% if 'add_path_tx_all' in n_af_val and n_af_val['add_path_tx_all'] == 'true' %}
neighbor {{nbr_name}} addpath-tx-all-paths
{% endif %}
{% if 'add_path_tx_bestpath' in n_af_val and n_af_val['add_path_tx_bestpath'] == 'true' %}
neighbor {{nbr_name}} addpath-tx-bestpath-per-AS
{% endif %}
{% if 'cap_orf' in n_af_val %}
neighbor {{nbr_name}} capability orf prefix-list {{n_af_val['cap_orf']}}
{% endif %}
{% if 'weight' in n_af_val %}
neighbor {{nbr_name}} weight {{n_af_val['weight']}}
{% endif %}
{% if 'prefix_list_in' in n_af_val %}
neighbor {{nbr_name}} prefix-list {{n_af_val['prefix_list_in']}} in
{% endif %}
{% if 'prefix_list_out' in n_af_val %}
neighbor {{nbr_name}} prefix-list {{n_af_val['prefix_list_out']}} out
{% endif %}
{# ------- route-map in --------------------------- #}
{% if 'route_map_in' in n_af_val %}
{% for map in n_af_val['route_map_in'] %}
neighbor {{nbr_name}} route-map {{map}} in
{% endfor %}
{% endif %}
{# ------- route-map in end --------------------------- #}
{# ------- route-map out --------------------------- #}
{% if 'route_map_out' in n_af_val %}
{% for map in n_af_val['route_map_out'] %}
neighbor {{nbr_name}} route-map {{map}} out
{% endfor %}
{% endif %}
{# ------- route-map out end --------------------------- #}
{% if 'unsuppress_map_name' in n_af_val %}
neighbor {{nbr_name}} unsuppress-map {{n_af_val['unsuppress_map_name']}}
{% endif %}
{% if 'filter_list_in' in n_af_val %}
neighbor {{nbr_name}} filter-list {{n_af_val['filter_list_in']}} in
{% endif %}
{% if 'filter_list_out' in n_af_val %}
neighbor {{nbr_name}} filter-list {{n_af_val['filter_list_out']}} out
{% endif %}
{# ------- attribute-unchanged --------------------------- #}
{% set attr = '' %}
{% if 'unchanged_as_path' in n_af_val and n_af_val['unchanged_as_path'] == 'true' %}
{% set attr = 'as-path ' %}
{% endif %}
{% if 'unchanged_med' in n_af_val and n_af_val['unchanged_med'] == 'true' %}
{% set attr = attr + 'med ' %}
{% endif %}
{% if 'unchanged_nexthop' in n_af_val and n_af_val['unchanged_nexthop'] == 'true' %}
{% set attr = attr + 'next-hop' %}
{% endif %}
{% if attr != '' %}
neighbor {{nbr_name}} attribute-unchanged {{attr}}
{% endif %}
{# ------- attribute-unchanged end --------------------------- #}

View File

@ -0,0 +1,103 @@
{# ------------------------------------------------------------- #}
{# this is called with the "vrf" matched #}
{# nbr_or_peer contains the information for the neighbor or peer #}
{# name_or_ip will be the IP or the name of the neighbor or peer #}
{# ------------------------------------------------------------- #}
{% set ns_intf = namespace(intf_arg = '') %}
{% if nbr_or_peer_type == 'peer-group' %}
neighbor {{name_or_ip}} peer-group
{% else %}
{% if not (name_or_ip | ipv4 or name_or_ip | ipv6) %}
{% set ns_intf.intf_arg = 'interface ' %}
{% endif %}
{% endif %}
{% set remote_as = '' %}
{% if 'asn' in nbr_or_peer %}
{% set remote_as = nbr_or_peer['asn'] %}
{% endif %}
{% if 'peer_type' in nbr_or_peer %}
{% set remote_as = nbr_or_peer['peer_type'] %}
{% endif %}
{% if remote_as != '' %}
neighbor {{name_or_ip}} {{ns_intf.intf_arg}}remote-as {{remote_as}}
{% endif %}
{% if 'peer_group_name' in nbr_or_peer %}
neighbor {{name_or_ip}} {{ns_intf.intf_arg}}peer-group {{nbr_or_peer['peer_group_name']}}
{% endif %}
{% if 'local_asn' in nbr_or_peer %}
neighbor {{name_or_ip}} local-as {{nbr_or_peer['local_asn']}}
{% endif %}
{% if 'name' in nbr_or_peer %}
neighbor {{name_or_ip}} description {{nbr_or_peer['name']}}
{% endif %}
{% if 'admin_status' in nbr_or_peer and nbr_or_peer['admin_status'] == 'false' %}
{% if 'shutdown_message' in nbr_or_peer %}
neighbor {{name_or_ip}} shutdown message {{nbr_or_peer['shutdown_message']}}
{% else %}
neighbor {{name_or_ip}} shutdown
{% endif %}
{% endif %}
{% if 'bfd' in nbr_or_peer and nbr_or_peer['bfd'] == 'true' %}
neighbor {{name_or_ip}} bfd
{% endif %}
{% if 'ttl_security_hops' in nbr_or_peer %}
neighbor {{name_or_ip}} ttl-security hops {{nbr_or_peer['ttl_security_hops']}}
{% endif %}
{% if 'auth_password' in nbr_or_peer %}
neighbor {{name_or_ip}} password {{nbr_or_peer['auth_password']}} encrypted
{% endif %}
{% if 'solo_peer' in nbr_or_peer and nbr_or_peer['solo_peer'] == 'true' %}
neighbor {{name_or_ip}} solo
{% endif %}
{% if 'peer_port' in nbr_or_peer %}
neighbor {{name_or_ip}} port {{nbr_or_peer['peer_port']}}
{% endif %}
{% if 'passive_mode' in nbr_or_peer and nbr_or_peer['passive_mode'] == 'true' %}
neighbor {{name_or_ip}} passive
{% endif %}
{% set mhop = '' %}
{% if 'ebgp_multihop' in nbr_or_peer and nbr_or_peer['ebgp_multihop'] == 'true' %}
{% set mhop = 255 %}
{% endif %}
{% if 'ebgp_multihop_ttl' in nbr_or_peer %}
{% set mhop = nbr_or_peer['ebgp_multihop_ttl'] %}
{% endif %}
{% if mhop != '' %}
neighbor {{name_or_ip}} ebgp-multihop {{mhop}}
{% endif %}
{% if 'disable_ebgp_connected_route_check' in nbr_or_peer and nbr_or_peer['disable_ebgp_connected_route_check'] == 'true' %}
neighbor {{name_or_ip}} disable-connected-check
{% endif %}
{% if 'enforce_first_as' in nbr_or_peer and nbr_or_peer['enforce_first_as'] == 'true' %}
neighbor {{name_or_ip}} enforce-first-as
{% endif %}
{% if 'local_addr' in nbr_or_peer %}
neighbor {{name_or_ip}} update-source {{nbr_or_peer['local_addr']}}
{% endif %}
{% if 'strict_capability_match' in nbr_or_peer and nbr_or_peer['strict_capability_match'] == true %}
neighbor {{name_or_ip}} strict-capability-match {{nbr_or_peer['strict_capability_match']}}
{% endif %}
{% if 'min_adv_interval' in nbr_or_peer %}
neighbor {{name_or_ip}} advertisement-interval {{nbr_or_peer['min_adv_interval']}}
{% endif %}
{% if 'keepalive' in nbr_or_peer and 'holdtime' in nbr_or_peer %}
neighbor {{name_or_ip}} timers {{nbr_or_peer['keepalive']}} {{nbr_or_peer['holdtime']}}
{% endif %}
{% if 'conn_retry' in nbr_or_peer %}
neighbor {{name_or_ip}} timers connect {{nbr_or_peer['conn_retry']}}
{% endif %}
{% if 'capability_dynamic' in nbr_or_peer and nbr_or_peer['capability_dynamic'] == 'true' %}
neighbor {{name_or_ip}} capability dynamic
{% endif %}
{% if 'capability_ext_nexthop' in nbr_or_peer and nbr_or_peer['capability_ext_nexthop'] == 'true' %}
neighbor {{name_or_ip}} capability extended-nexthop
{% endif %}
{% if 'dont_negotiate_capability' in nbr_or_peer and nbr_or_peer['dont_negotiate_capability'] == 'true' %}
neighbor {{name_or_ip}} dont-capability-negotiate
{% endif %}
{% if 'enforce_multihop' in nbr_or_peer and nbr_or_peer['enforce_multihop'] == 'true' %}
neighbor {{name_or_ip}} enforce-multihop
{% endif %}
{% if 'override_capability' in nbr_or_peer and nbr_or_peer['override_capability'] == 'true' %}
neighbor {{name_or_ip}} override-capability
{% endif %}

View File

@ -0,0 +1,30 @@
{# ------------------------------------------------------------------------------------ #}
{% if (PREFIX_SET is defined and PREFIX_SET|length > 0) and
(PREFIX is defined and PREFIX|length > 0) %}
{% set modes = ['IPv4', 'IPv6'] %}
{% set ip_str = {'IPv4':'ip', 'IPv6':'ipv6' } %}
{% for md in modes %}
!
{% for key, val in PREFIX_SET.items() %}
{% if 'mode' in val %}
{% for pf_key, pf_val in PREFIX.items() %}
{% if pf_key[0] == key and md == val['mode'] %}
{% if pf_key[2] == 'exact' %}
{{ip_str[md]}} prefix-list {{key}} permit {{pf_key[1]}}
{% else %}
{% set len = pf_key[1].split('/')[1] %}
{% set rb = pf_key[2].split('..')[0] %}
{% set re = pf_key[2].split('..')[1] %}
{% if rb > len %}
{{ip_str[md]}} prefix-list {{key}} permit {{pf_key[1]}} ge {{rb}} le {{re}}
{% else %}
{{ip_str[md]}} prefix-list {{key}} permit {{pf_key[1]}} le {{re}}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{# ------------------------------------------------------------------------------------ #}

View File

@ -0,0 +1,150 @@
{% if ROUTE_MAP is defined and ROUTE_MAP|length > 0 %}
{% for rm_key, rm_val in ROUTE_MAP.items() %}
{% if 'route_operation' in rm_val %}
!
route-map {{rm_key[0]}} {{rm_val['route_operation']}} {{rm_key[1]}}
{% if 'match_as_path' in rm_val %}
match as-path {{rm_val['match_as_path']}}
{% endif %}
{% if 'call_route_map' in rm_val %}
call {{rm_val['call_route_map']}}
{% endif %}
{% if 'match_community' in rm_val %}
match community {{rm_val['match_community']}}
{% endif %}
{% if 'match_ext_community' in rm_val %}
match extcommunity {{rm_val['match_ext_community']}}
{% endif %}
{% if 'match_interface' in rm_val %}
match interface {{rm_val['match_interface']}}
{% endif %}
{% if 'match_tag' in rm_val %}
match tag {{rm_val['match_tag'][0]}}
{% endif %}
{% if 'match_src_vrf' in rm_val %}
match source-vrf {{rm_val['match_src_vrf']}}
{% endif %}
{# ---------------match ip/ipv6-Start-------------------------- #}
{% set ip_str = {'ipv4':'ip', 'ipv6':'ipv6' } %}
{% if PREFIX_SET is defined and PREFIX_SET|length > 0 %}
{% if 'match_prefix_set' in rm_val %}
{% for pfx_key, pfx_val in PREFIX_SET.items() %}
{% if rm_val['match_prefix_set'] == pfx_key %}
match {{ip_str[pfx_val['mode']]}} address prefix-list {{rm_val['match_prefix_set']}}
{% endif %}
{% endfor %}
{% endif %}
{% if 'match_next_hop_set' in rm_val %}
{% for pfx_key, pfx_val in PREFIX_SET.items() %}
{% if rm_val['match_next_hop_set'] == pfx_key %}
match {{ip_str[pfx_val['mode']]}} next-hop prefix-list {{rm_val['match_next_hop_set']}}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{# ---------------match ip/ipv6- End-------------------------- #}
{% if 'match_local_pref' in rm_val %}
match local-preference {{rm_val['match_local_pref']}}
{% endif %}
{% if 'match_med' in rm_val %}
match metric {{rm_val['match_med']}}
{% endif %}
{% if 'match_origin' in rm_val %}
match origin {{rm_val['match_origin']|lower}}
{% endif %}
{% if 'match_neighbor' in rm_val %}
match peer {{rm_val['match_neighbor'][0]}}
{% endif %}
{% if 'match_protocol' in rm_val %}
match source-protocol {{rm_val['match_protocol']}}
{% endif %}
{# ---------------set as-path prepend - Start ----------------- #}
{% if 'set_asn' in rm_val and 'set_repeat_asn' in rm_val %}
{% set ns = namespace(as_str='') %}
{% if rm_val['set_repeat_asn'] > 0 %}
{% for i in range(rm_val['set_repeat_asn']|int) %}
{% set ns.as_str = ns.as_str+' '+rm_val['set_asn'] %}
{% endfor %}
{% else %}
{% set ns.as_str = rm_val['set_asn'] %}
{% endif %}
set as-path prepend{{ns.as_str}}
{% endif %}
{# ---------------set as-path prepend - End ------------------- #}
{# ---------------set community - Start------------------------ #}
{% if 'set_community_inline' in rm_val %}
{% set ns = namespace(comms = '') %}
{% for cm in rm_val['set_community_inline'] %}
{% set ns.comms = ns.comms + ' ' + cm %}
{% endfor %}
set community{{ns.comms}}
{% endif %}
{# ---------------set community - End-------------------------- #}
{% if 'set_community_ref' in rm_val %}
set community {{rm_val['set_community_ref']}}
{% endif %}
{# ---------------set extcommunity - Start--------------------- #}
{% if 'set_ext_community_inline' in rm_val %}
{% set ec_ns = namespace(rt_str='', soo_str='') %}
{% for ext_comm in rm_val['set_ext_community_inline'] %}
{% set comm = ext_comm.split(':') %}
{% if comm[0] == 'route-target' %}
{% set ec_ns.rt_str = ec_ns.rt_str+' '+comm[1]+':'+comm[2] %}
{% endif %}
{% if comm[0] == 'route-origin' %}
{% set ec_ns.soo_str = ec_ns.soo_str+' '+comm[1]+':'+comm[2] %}
{% endif %}
{% endfor %}
{% if ec_ns.rt_str != '' %}
set extcommunity rt{{ec_ns.rt_str}}
{% endif %}
{% if ec_ns.soo_str != '' %}
set extcommunity soo{{ec_ns.rt_str}}
{% endif %}
{% endif %}
{# ---------------set extcommunity - End----------------------- #}
{% if 'set_ext_community_ref' in rm_val %}
set extcommunity {{rm_val['set_ext_community_ref']}}
{% endif %}
{% if 'set_next_hop' in rm_val %}
set ip next-hop {{rm_val['set_next_hop']}}
{% endif %}
{% if 'set_ipv6_next_hop_global' in rm_val %}
set ipv6 next-hop global {{rm_val['set_ipv6_next_hop_global']}}
{% endif %}
{% if 'set_ipv6_next_hop_prefer_global' in rm_val and rm_val['set_ipv6_next_hop_prefer_global'] == 'true' %}
set ipv6 next-hop prefer-global
{% endif %}
{% if 'set_local_preference' in rm_val %}
set local-preference {{rm_val['set_local_preference']}}
{% endif %}
{# ---------------set metric and med - Start--------------------- #}
{% if 'set_metric_action' in rm_val %}
{% if 'set_metric' in rm_val %}
{% if rm_val['set_metric_action'] == 'METRIC_SET_VALUE' %}
set metric {{rm_val['set_metric']}}
{% elif rm_val['set_metric_action'] == 'METRIC_ADD_VALUE' %}
set metric +{{rm_val['set_metric']}}
{% elif rm_val['set_metric_action'] == 'METRIC_SUBTRACT_VALUE' %}
set metric -{{rm_val['set_metric']}}
{% endif %}
{% endif %}
{% if rm_val['set_metric_action'] == 'METRIC_SET_RTT' %}
set metric rtt
{% elif rm_val['set_metric_action'] == 'METRIC_ADD_RTT' %}
set metric +rtt
{% elif rm_val['set_metric_action'] == 'METRIC_SUBTRACT_RTT' %}
set metric -rtt
{% endif %}
{% elif 'set_med' in rm_val %}
set metric {{rm_val['set_med']}}
{% elif 'set_metric' in rm_val %}
set metric {{rm_val['set_metric']}}
{% endif %}
{# ---------------set metric and med - End--------------------- #}
{% if 'set_origin' in rm_val %}
set origin {{rm_val['set_origin']|lower}}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}

View File

@ -0,0 +1,15 @@
{% block banner %}
! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
! generated by templates/quagga/bgpd.conf.j2 with config DB data
! file: bgpd.conf
!
{% endblock banner %}
!
{% include "common/daemons.common.conf.j2" %}
!
agentx
!
{% include "bgpd.conf.db.j2" %}
!
! end of template: bgpd/bgpd.conf.j2
!

View File

@ -0,0 +1,30 @@
!
{% block banner %}
! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
! generated by templates/frr.conf.j2 with config DB data
! file: frr.conf
!
{% endblock banner %}
!
{% include "common/daemons.common.conf.j2" %}
!
agentx
!
{% include "zebra/zebra.interfaces.conf.j2" %}
!
{% if MGMT_VRF_CONFIG %}
{% if MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == 'false' %}
{% include "staticd.db.default_route.conf.j2" %}
{% endif %}
{% else %}
{% include "staticd.db.default_route.conf.j2" %}
{% endif %}
!
{% include "staticd.db.conf.j2" %}
!
{% include "bgpd.conf.db.j2" %}
!
{% include "ospfd.conf.j2" %}
!
{% include "bfdd.conf.j2" %}
!

View File

@ -0,0 +1,37 @@
{% set areaid = areakey[1] %}
{% if 'authentication' in area_instance %}
{% if area_instance['authentication'] == "MD5HMAC" %}
area {{ areaid }} authentication message-digest
{% else %}
area {{ areaid }} authentication
{% endif %}
{% endif %}
{% if 'stub-no-summary' in area_instance %}
{% if area_instance['stub-no-summary'] == 'true' %}
area {{ areaid }} stub no-summary
{% endif %}
{% else %}
{% if 'stub' in area_instance %}
{% if area_instance['stub'] == 'true' %}
area {{ areaid }} stub
{% endif %}
{% endif %}
{% endif %}
{% if 'stub-default-cost' in area_instance %}
area {{ areaid }} default-cost {{ area_instance['stub-default-cost'] }}
{% endif %}
{% if 'import-list' in area_instance %}
area {{ areaid }} import-list {{ area_instance['import-list'] }}
{% endif %}
{% if 'export-list' in area_instance %}
area {{ areaid }} export-list {{ area_instance['export-list'] }}
{% endif %}
{% if 'filter-list-in' in area_instance %}
area {{ areaid }} filter-list prefix {{ area_instance['filter-list-in'] }} in
{% endif %}
{% if 'filter-list-out' in area_instance %}
area {{ areaid }} filter-list prefix {{ area_instance['filter-list-out'] }} out
{% endif %}
{% if 'shortcut' in area_instance %}
area {{ areaid }} shortcut {{ (area_instance['shortcut']).lower() }}
{% endif %}

View File

@ -0,0 +1,129 @@
{# ------------------------------------------------------------------------------------ #}
{# ------------------------------------------------------------------------------------ #}
{% if OSPFV2_ROUTER is defined and OSPFV2_ROUTER|length > 0 %}
{% for vrf, ospf_instance in OSPFV2_ROUTER.items() %}
!
router ospf vrf {{ vrf }}
{% if 'router-id' in ospf_instance %}
ospf router-id {{ ospf_instance['router-id'] }}
{% endif %}
{% if 'abr-type' in ospf_instance %}
ospf abr-type {{ (ospf_instance['abr-type']).lower() }}
{% endif %}
{% if 'auto-cost-reference-bandwidth' in ospf_instance %}
auto-cost reference-bandwidth {{ (ospf_instance['auto-cost-reference-bandwidth']) }}
{% endif %}
{% if 'log-adjacency-changes' in ospf_instance %}
{% if ospf_instance['log-adjacency-changes'] == 'DETAIL' %}
log-adjacency-changes detail
{% else %}
log-adjacency-changes
{% endif %}
{% endif %}
{% if 'default-metric' in ospf_instance %}
default-metric {{ ospf_instance['default-metric'] }}
{% endif %}
{% if 'ospf-rfc1583-compatible' in ospf_instance %}
{% if ospf_instance['ospf-rfc1583-compatible'] == 'true' %}
compatible rfc1583
{% endif %}
{% endif %}
{% if 'passive-interface-default' in ospf_instance %}
passive-interface default
{% endif %}
{% if 'write-multiplier' in ospf_instance %}
write-multiplier {{ ospf_instance['write-multiplier'] }}
{% endif %}
{% if 'spf-throttle-delay' in ospf_instance and 'spf-initial-delay' in ospf_instance and 'spf-maximum-delay' in ospf_instance %}
timers throttle spf {{ ospf_instance['spf-throttle-delay'] }} {{ ospf_instance['spf-initial-delay'] }} {{ ospf_instance['spf-maximum-delay'] }}
{% endif %}
{% if 'lsa-min-interval-timer' in ospf_instance %}
timers throttle lsa all {{ ospf_instance['lsa-min-interval-timer'] }}
{% endif %}
{% if 'lsa-min-arrival-timer' in ospf_instance %}
timers lsa min-arrival {{ ospf_instance['lsa-min-arrival-timer'] }}
{% endif %}
{% if 'lsa-refresh-timer' in ospf_instance %}
refresh timer {{ ospf_instance['lsa-refresh-timer'] }}
{% endif %}
{% if 'max-metric-administrative' in ospf_instance %}
{% if ospf_instance['max-metric-administrative'] == 'true' %}
max-metric router-lsa administrative
{% endif %}
{% endif %}
{% if 'max-metric-on-startup' in ospf_instance %}
max-metric router-lsa on-startup {{ ospf_instance['max-metric-on-startup'] }}
{% endif %}
{% if 'max-metric-on-shutdown' in ospf_instance %}
max-metric router-lsa on-shutdown {{ ospf_instance['max-metric-on-shutdown'] }}
{% endif %}
{% if 'distance-all' in ospf_instance %}
distance {{ ospf_instance['distance-all'] }}
{% endif %}
{% if 'distance-inter-area' in ospf_instance or 'distance-intra-area' in ospf_instance or 'distance-external' in ospf_instance%}
{% set distance_cmd = '' %}
{% set distance_cmd = 'distance ospf' %}
{% if 'distance-intra-area' in ospf_instance %}
{% set distance_cmd = distance_cmd + ' intra-area ' + ospf_instance['distance-intra-area'] %}
{% endif %}
{% if 'distance-inter-area' in ospf_instance %}
{% set distance_cmd = distance_cmd + ' inter-area ' + ospf_instance['distance-inter-area'] %}
{% endif %}
{% if 'distance-external' in ospf_instance %}
{% set distance_cmd = distance_cmd + ' external ' + ospf_instance['distance-external'] %}
{% endif %}
{{ distance_cmd }}
{% endif %}
{# -------OSPFV2_ROUTER end --------------------------- #}
{# -------OSPFV2_ROUTER_AREA Begin --------------------------- #}
{% if OSPFV2_ROUTER_AREA is defined and OSPFV2_ROUTER_AREA|length > 0 %}
{% for areakey, area_instance in OSPFV2_ROUTER_AREA.items() %}
{% include "ospfd.conf.db.area.j2" %}
{% endfor %}
{% endif %}
{# -------OSPFV2_ROUTER_AREA end --------------------------- #}
{# -------OSPFV2_ROUTER_AREA_NETWORK Begin --------------------------- #}
{% if OSPFV2_ROUTER_AREA_NETWORK is defined and OSPFV2_ROUTER_AREA_NETWORK|length > 0 %}
{% for networkkey, ospf_network_instance in OSPFV2_ROUTER_AREA_NETWORK.items() %}
{% set networkareaid = networkkey[1] %}
{% set networkid = networkkey[2] %}
network {{ networkid }} area {{ networkareaid }}
{% endfor %}
{% endif %}
{# -------OSPFV2_ROUTER_AREA_NETWORK end --------------------------- #}
{# -------OSPFV2_ROUTER_AREA_VIRTUAL_LINK Begin --------------------------- #}
{% if OSPFV2_ROUTER_AREA_VIRTUAL_LINK is defined and OSPFV2_ROUTER_AREA_VIRTUAL_LINK|length > 0 %}
{% for vlinkkey, vlink_instance in OSPFV2_ROUTER_AREA_VIRTUAL_LINK.items() %}
{% include "ospfd.conf.db.vlink.j2" %}
{% endfor %}
{% endif %}
{# -------OSPFV2_ROUTER_AREA_VIRTUAL_LINK end --------------------------- #}
{# -------OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE Begin --------------------------- #}
{% if OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE is defined and OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE|length > 0 %}
{% for rangekey, area_range_instance in OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE.items() %}
{% include "ospfd.conf.db.policyrange.j2" %}
{% endfor %}
{% endif %}
{# -------OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE end --------------------------- #}
{# -------OSPFV2_ROUTER_DISTRIBUTE_ROUTE Begin --------------------------- #}
{% if OSPFV2_ROUTER_DISTRIBUTE_ROUTE is defined and OSPFV2_ROUTER_DISTRIBUTE_ROUTE|length > 0 %}
{% for routekey, route_instance in OSPFV2_ROUTER_DISTRIBUTE_ROUTE.items() %}
{% include "ospfd.conf.db.distributeroute.j2" %}
{% endfor %}
{% endif %}
{# -------OSPFV2_ROUTER_DISTRIBUTE_ROUTE end --------------------------- #}
{# -------OSPFV2_ROUTER_PASSIVE_INTERFACE Begin --------------------------- #}
{% if OSPFV2_ROUTER_PASSIVE_INTERFACE is defined and OSPFV2_ROUTER_PASSIVE_INTERFACE|length > 0 %}
{% for passintfkey, passintf_instance in OSPFV2_ROUTER_PASSIVE_INTERFACE.items() %}
{% set passintfname = passintfkey[1] %}
{% set passintfaddr = passintfkey[2] %}
{% if passintfaddr == '0.0.0.0' %}
passive-interface {{ passintfname }}
{% else %}
passive-interface {{ passintfname }} {{ passintfaddr }}
{% endif %}
{% endfor %}
{% endif %}
{# -------OSPFV2_ROUTER_PASSIVE_INTERFACE end --------------------------- #}
{% endfor %}
{% endif %}

View File

@ -0,0 +1,52 @@
{% set routeproto = routekey[1] %}
{% set routedirection = routekey[2] %}
{% set generic_protocols = [ "BGP", "KERNEL", "STATIC", "DIRECTLY_CONNECTED"] %}
{% if routeproto == "DEFAULT_ROUTE" and routedirection == "IMPORT" %}
{% set defaultinfo_cmd = '' %}
{% set defaultinfo_cmd = 'default-information originate' %}
{% if 'always' in route_instance %}
{% if route_instance['always'] == 'true' %}
{% set defaultinfo_cmd = defaultinfo_cmd + ' always' %}
{% endif %}
{% endif %}
{% if 'metric' in route_instance %}
{% set defaultinfo_cmd = defaultinfo_cmd + ' metric ' + route_instance['metric'] %}
{% endif %}
{% if 'metric-type' in route_instance %}
{% if route_instance['metric-type'] == "TYPE_1"%}
{% set defaultinfo_cmd = defaultinfo_cmd + ' metric-type ' + '1' %}
{% endif %}
{% endif %}
{% if 'route-map' in route_instance %}
{% set defaultinfo_cmd = defaultinfo_cmd + ' route-map ' + route_instance['route-map'] %}
{% endif %}
{{ defaultinfo_cmd }}
{% elif routedirection == "IMPORT" and routeproto in generic_protocols %}
{% set redistribute_cmd = '' %}
{% if routeproto == "DIRECTLY_CONNECTED" %}
{% set redistribute_cmd = 'redistribute ' + 'connected' %}
{% else %}
{% set redistribute_cmd = 'redistribute ' + routeproto.lower() %}
{% endif %}
{% if 'metric' in route_instance %}
{% set redistribute_cmd = redistribute_cmd + ' metric ' + route_instance['metric'] %}
{% endif %}
{% if 'metric-type' in route_instance %}
{% if route_instance['metric-type'] == "TYPE_1"%}
{% set redistribute_cmd = redistribute_cmd + ' metric-type ' + '1' %}
{% endif %}
{% endif %}
{% if 'route-map' in route_instance %}
{% set redistribute_cmd = redistribute_cmd + ' route-map ' + route_instance['route-map'] %}
{% endif %}
{{ redistribute_cmd }}
{% elif routedirection == "EXPORT" and routeproto in generic_protocols %}
{% if 'route-map' in route_instance %}
{% if routeproto == "DIRECTLY_CONNECTED" %}
distribute-list {{ route_instance['route-map'] }} out connected
{% else %}
distribute-list {{ route_instance['route-map'] }} out {{ routeproto.lower() }}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,76 @@
{# ------------------------------------------------------------------------------------ #}
{# ------------------------------------------------------------------------------------ #}
{% if OSPFV2_INTERFACE is defined and OSPFV2_INTERFACE|length > 0 %}
{% for (intfkey, ospf_intf_instance) in OSPFV2_INTERFACE.items() %}
!
{% set intfname = intfkey[0] %}
{% set intfaddr = intfkey[1] %}
{% if intfaddr == "0.0.0.0" %}
{% set intfaddr = "" %}
{% endif %}
interface {{ intfname }}
{% if 'area-id' in ospf_intf_instance %}
ip ospf area {{ ospf_intf_instance['area-id'] }} {{ intfaddr }}
{% endif %}
{% if 'network-type' in ospf_intf_instance %}
{% if ospf_intf_instance['network-type'] == 'BROADCAST_NETWORK' %}
ip ospf network broadcast {{ intfaddr }}
{% endif %}
{% if ospf_intf_instance['network-type'] == 'POINT_TO_POINT_NETWORK' %}
ip ospf network point-to-point {{ intfaddr }}
{% endif %}
{% endif %}
{% if 'metric' in ospf_intf_instance %}
ip ospf cost {{ ospf_intf_instance['metric'] }} {{ intfaddr }}
{% endif %}
{% if 'priority' in ospf_intf_instance %}
ip ospf priority {{ ospf_intf_instance['priority'] }} {{ intfaddr }}
{% endif %}
{% if 'mtu-ignore' in ospf_intf_instance %}
{% if ospf_intf_instance['mtu-ignore'] == 'true' %}
ip ospf mtu-ignore {{ intfaddr }}
{% endif %}
{% endif %}
{% if 'bfd-enable' in ospf_intf_instance %}
{% if ospf_intf_instance['bfd-enable'] == 'true' %}
ip ospf bfd
{% endif %}
{% endif %}
{% if 'authentication-type' in ospf_intf_instance %}
{% if ospf_intf_instance['authentication-type'] == 'MD5HMAC' %}
ip ospf authentication message-digest {{ intfaddr }}
{% endif %}
{% if ospf_intf_instance['authentication-type'] == 'NONE' %}
ip ospf authentication null {{ intfaddr }}
{% endif %}
{% if ospf_intf_instance['authentication-type'] == 'TEXT' %}
ip ospf authentication {{ intfaddr }}
{% endif %}
{% endif %}
{% if 'authentication-key' in ospf_intf_instance %}
ip ospf authentication-key {{ ospf_intf_instance['authentication-key'] }} {{ intfaddr }}
{% endif %}
{% if 'authentication-key-id' in ospf_intf_instance and 'authentication-md5-key' in ospf_intf_instance %}
ip ospf message-digest-key {{ ospf_intf_instance['authentication-key-id'] }} md5 {{ ospf_intf_instance['authentication-md5-key'] }} {{ intfaddr }}
{% endif %}
{% if 'dead-interval' in ospf_intf_instance %}
ip ospf dead-interval {{ ospf_intf_instance['dead-interval'] }} {{ intfaddr }}
{% endif %}
{% if 'dead-interval-minimal' in ospf_intf_instance %}
{% if 'hello-multiplier' in ospf_intf_instance %}
ip ospf dead-interval minimal hello-multiplier {{ ospf_intf_instance['hello-multiplier'] }} {{ intfaddr }}
{% else %}
ip ospf dead-interval minimal {{ intfaddr }}
{% endif %}
{% endif %}
{% if 'hello-interval' in ospf_intf_instance %}
ip ospf hello-interval {{ ospf_intf_instance['hello-interval'] }} {{ intfaddr }}
{% endif %}
{% if 'retransmission-interval' in ospf_intf_instance %}
ip ospf retransmit-interval {{ ospf_intf_instance['retransmission-interval'] }} {{ intfaddr }}
{% endif %}
{% if 'transmit-delay' in ospf_intf_instance %}
ip ospf transmit-delay {{ ospf_intf_instance['transmit-delay'] }} {{ intfaddr }}
{% endif %}
{% endfor %}
{% endif %}

View File

@ -0,0 +1,16 @@
{% set rangeareaid = rangekey[1] %}
{% set rangeid = rangekey[2] %}
area {{ rangeareaid }} range {{ rangeid }}
{% if 'advertise' in area_range_instance %}
{% if area_range_instance['advertise'] == 'true' %}
area {{ rangeareaid }} range {{ rangeid }} advertise
{% else %}
area {{ rangeareaid }} range {{ rangeid }} not-advertise
{% endif %}
{% endif %}
{% if 'metric' in area_range_instance %}
area {{ rangeareaid }} range {{ rangeid }} advertise cost {{ area_range_instance['metric'] }}
{% endif %}
{% if 'substitue-prefix' in area_range_instance %}
area {{ rangeareaid }} range {{ rangeid }} substitute {{ area_range_instance['substitue-prefix'] }}
{% endif %}

View File

@ -0,0 +1,29 @@
{% set vlinkareaid = vlinkkey[1] %}
{% set vlinkid = vlinkkey[2] %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }}
{% if 'authentication' in vlink_instance %}
{% if vlink_instance['authentication'] == 'MD5HMAC' %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} authentication message-digest
{% else %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} null
{% endif %}
{% endif %}
{% if 'authentication-key' in vlink_instance %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} authentication-key {{ vlink_instance['authentication-key'] }}
{% endif %}
{% if 'authentication-key-id' in vlink_instance and 'authentication-md5-key' in vlink_instance %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} authentication message-digest message-digest-key {{ vlink_instance['authentication-key-id'] }} md5 {{ vlink_instance['authentication-md5-key'] }}
{% endif %}
{% if 'dead-interval' in vlink_instance %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} dead-interval {{ vlink_instance['dead-interval'] }}
{% endif %}
{% if 'hello-interval' in vlink_instance %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} hello-interval {{ vlink_instance['hello-interval'] }}
{% endif %}
{% if 'retransmission-interval' in vlink_instance %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} retransmit-interval {{ vlink_instance['retransmission-interval'] }}
{% endif %}
{% if 'transmit-delay' in vlink_instance %}
area {{ vlinkareaid }} virtual-link {{ vlinkid }} transmit-delay {{ vlink_instance['transmit-delay'] }}
{% endif %}

View File

@ -0,0 +1,6 @@
! template: ospfd/ospfd.conf.j2
!
! OSPF configuration using config DB OSPF instance tables
!
{% include "ospfd.conf.db.comm_list.j2" %}
{% include "ospfd.conf.db.interface.j2" %}

View File

@ -0,0 +1,22 @@
{% block banner %}
! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
! generated by templates/frr/staticd.conf.j2 using config DB data
! file: staticd.conf
!
{% endblock banner %}
!
{% with agentx='false' %}
{% include "common/daemons.common.conf.j2" %}
{% endwith %}
!
{% if MGMT_VRF_CONFIG %}
{% if MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == 'false' %}
{% include "staticd.db.default_route.conf.j2" %}
{% endif %}
{% else %}
{% include "staticd.db.default_route.conf.j2" %}
{% endif %}
!
{% include "staticd.db.conf.j2" %}
!

View File

@ -0,0 +1,153 @@
! template: staticd/staticd.db.conf.j2
!
! Static Route configuration using config DB static route table
!
{% macro iproute(ip_prefix, nh_blackhole, nh_ip, nh_intf, nh_dist, nh_tag, nh_vrf) %}
{%- set ns = namespace(str = None) %}
{%- set ip_addr = ip_prefix.split('/')[0] %}
{%- if ip_addr|ipv4 %}
{%- set ns.str = 'ip route' %}
{%- else %}
{%- set ns.str = 'ipv6 route' %}
{%- endif %}
{%- if nh_blackhole %}
{#- ------------------------------ blackhole route ------------------------------ #}
{%- for item in [ip_prefix, 'blackhole', nh_tag, nh_dist] %}
{%- if item != None %}
{%- set ns.str = ns.str + ' ' + item %}
{%- endif %}
{%- endfor %}
{%- else %}
{#- ------------------------------ non-blackhole route ------------------------------ #}
{%- for item in [ip_prefix, nh_ip, nh_intf, nh_tag, nh_dist, nh_vrf] %}
{%- if item != None %}
{%- set ns.str = ns.str + ' ' + item %}
{%- endif %}
{%- endfor %}
{%- endif %}
{{ ns.str }}
{%- endmacro %}
{% if STATIC_ROUTE is defined and STATIC_ROUTE|length > 0 %}
{%- set vrf_rt_list = {} %}
{%- for key, val in STATIC_ROUTE.items() %}
{#- ------------------------------ for each route - start ------------------------------ #}
{%- set rt = namespace(vrf = 'default', ip_prefix = '', nh_num = 0, nh_list = [], valid = True) %}
{%- if key is not string and key|length > 1 %}
{%- set rt.vrf = key[0] %}
{%- set rt.ip_prefix = key[1] %}
{%- else %}
{%- set rt.ip_prefix = key %}
{%- endif %}
{%- set nh_attr = {} %}
{#- ------------------------------ get nh count - start ------------------------------ #}
{%- for fld_key, fld_val in val.items() if rt.valid %}
{%- set attr_list = fld_val.split(',') %}
{%- if rt.nh_num == 0 %}
{%- set rt.nh_num = attr_list|length %}
{%- else %}
{%- if rt.nh_num != attr_list|length %}
{%- set rt.valid = False %}
{%- endif %}
{%- endif %}
{%- if nh_attr.update({fld_key: attr_list}) %}
{%- endif %}
{%- endfor %}
{#- ------------------------------ get nh count - end ------------------------------ #}
{%- if rt.valid %}
{%- for nh_idx in range(rt.nh_num) %}
{#- ------------------------------ parse nh - start ------------------------------ #}
{%- set nh = namespace(blackhole = False, ip = None, intf = None, dist = None, tag = None, vrf = None) %}
{#- ------------------------------ nexthop blackhole ------------------------------ #}
{%- if 'blackhole' in nh_attr %}
{%- set nh.blackhole = nh_attr['blackhole'][nh_idx] %}
{%- if nh.blackhole == 'true' %}
{%- set nh.blackhole = True %}
{%- else %}
{%- set nh.blackhole = False %}
{%- endif %}
{%- endif %}
{#- ------------------------------ nexthop IP ------------------------------ #}
{%- if 'nexthop' in nh_attr %}
{%- set nh.ip = nh_attr['nexthop'][nh_idx] %}
{%- if nh.ip == '0.0.0.0' or nh.ip == '::' %}
{%- set nh.ip = None %}
{%- endif %}
{%- endif %}
{#- ------------------------------ nexthop interface ------------------------------ #}
{%- if 'ifname' in nh_attr %}
{%- set nh.intf = nh_attr['ifname'][nh_idx] %}
{%- if nh.intf == '' %}
{%- set nh.intf = None %}
{%- endif %}
{%- endif %}
{#- ------------------------------ nexthop distance ------------------------------ #}
{%- if 'distance' in nh_attr %}
{%- set nh.dist = nh_attr['distance'][nh_idx] %}
{%- if nh.dist == '0' %}
{%- set nh.dist = None %}
{%- endif %}
{%- endif %}
{#- ------------------------------ nexthop tag ------------------------------ #}
{%- if 'tag' in nh_attr %}
{%- set nh.tag = nh_attr['tag'][nh_idx] %}
{%- if nh.tag == '0' %}
{%- set nh.tag = None %}
{%- endif %}
{%- if nh.tag != None %}
{%- set nh.tag = 'tag ' + nh.tag %}
{%- endif %}
{%- endif %}
{#- ------------------------------ nexthop VRF ------------------------------ #}
{%- if 'nexthop-vrf' in nh_attr %}
{%- set nh.vrf = nh_attr['nexthop-vrf'][nh_idx] %}
{%- if nh.vrf == '' %}
{%- set nh.vrf = None %}
{%- endif %}
{%- if nh.vrf != None %}
{%- set nh.vrf = 'nexthop-vrf ' + nh.vrf %}
{%- endif %}
{%- endif %}
{#- ------------------------------ parse nh - end ------------------------------ #}
{%- if nh.blackhole or nh.ip != None or nh.intf != None %}
{%- if rt.nh_list.append(nh) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{#- ------------------------------ for each route - end ------------------------------ #}
{%- if not rt.vrf in vrf_rt_list %}
{%- if vrf_rt_list.update({rt.vrf: []}) %}
{%- endif %}
{%- endif %}
{%- if vrf_rt_list[rt.vrf].append(rt) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{# ------------------------------ dump route - start ------------------------------ #}
{# ------------------------------ default VRF ------------------------------ #}
{% for vrf, rt_list in vrf_rt_list.items() if vrf == 'default' %}
{% for rt in rt_list %}
{% if rt.valid %}
{% for nh in rt.nh_list %}
{{ iproute(rt.ip_prefix, nh.blackhole, nh.ip, nh.intf, nh.dist, nh.tag, nh.vrf) }}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
{# ------------------------------ non-default VRF ------------------------------ #}
{% for vrf, rt_list in vrf_rt_list.items() if vrf != 'default' %}
!
vrf {{ vrf }}
{% for rt in rt_list %}
{% if rt.valid %}
{% for nh in rt.nh_list %}
{{ iproute(rt.ip_prefix, nh.blackhole, nh.ip, nh.intf, nh.dist, nh.tag, nh.vrf) }}
{% endfor %}
{% endif %}
{% endfor %}
exit-vrf
!
{% endfor %}
{# ------------------------------ dump route - end ------------------------------ #}
{% endif %}

View File

@ -0,0 +1,9 @@
!
{% block default_route %}
! set static default route to mgmt gateway as a backup to learned default
{% if MGMT_INTERFACE %}
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
{% endfor %}
{% endif %}
{% endblock default_route %}
!

View File

@ -0,0 +1,176 @@
import copy
import re
from unittest.mock import MagicMock, NonCallableMagicMock, patch
swsssdk_module_mock = MagicMock(ConfigDBConnector = NonCallableMagicMock)
@patch.dict('sys.modules', swsssdk = swsssdk_module_mock)
def test_contructor():
from frrcfgd.frrcfgd import BGPConfigDaemon
daemon = BGPConfigDaemon()
daemon.start()
for table, hdlr in daemon.table_handler_list:
daemon.config_db.subscribe.assert_any_call(table, hdlr)
daemon.config_db.pubsub.psubscribe.assert_called_once()
daemon.stop()
daemon.config_db.sub_thread.stop.assert_called()
daemon.config_db.sub_thread.is_alive.assert_called_once()
daemon.config_db.sub_thread.join.assert_called_once()
class CmdMapTestInfo:
data_buf = {}
def __init__(self, table, key, data, exp_cmd, no_del = False, neg_cmd = None,
chk_data = None, daemons = None, ignore_tail = False):
self.table_name = table
self.key = key
self.data = data
self.vtysh_cmd = exp_cmd
self.no_del = no_del
self.vtysh_neg_cmd = neg_cmd
self.chk_data = chk_data
self.daemons = daemons
self.ignore_tail = ignore_tail
@classmethod
def add_test_data(cls, test):
assert(isinstance(test.data, dict))
cls.data_buf.setdefault(
test.table_name, {}).setdefault(test.key, {}).update(test.data)
@classmethod
def del_test_data(cls, test):
assert(test.table_name in cls.data_buf and
test.key in cls.data_buf[test.table_name])
cache_data = cls.data_buf[test.table_name][test.key]
assert(isinstance(test.data, dict))
for k, v in test.data.items():
assert(k in cache_data and cache_data[k] == v)
del(cache_data[k])
@classmethod
def get_test_data(cls, test):
assert(test.table_name in cls.data_buf and
test.key in cls.data_buf[test.table_name])
return copy.deepcopy(cls.data_buf[test.table_name][test.key])
@staticmethod
def compose_vtysh_cmd(cmd_list, negtive = False):
cmdline = 'vtysh'
for cmd in cmd_list:
cmd = cmd.format('no ' if negtive else '')
cmdline += " -c '%s'" % cmd
return cmdline
def check_running_cmd(self, mock, is_del):
if is_del:
vtysh_cmd = self.vtysh_cmd if self.vtysh_neg_cmd is None else self.vtysh_neg_cmd
else:
vtysh_cmd = self.vtysh_cmd
if callable(vtysh_cmd):
cmds = []
for call in mock.call_args_list:
assert(call[0][0] == self.table_name)
cmds.append(call[0][1])
vtysh_cmd(is_del, cmds, self.chk_data)
else:
if self.ignore_tail is None:
mock.assert_called_with(self.table_name, self.compose_vtysh_cmd(vtysh_cmd, is_del),
True, self.daemons)
else:
mock.assert_called_with(self.table_name, self.compose_vtysh_cmd(vtysh_cmd, is_del),
True, self.daemons, self.ignore_tail)
def hdl_confed_peers_cmd(is_del, cmd_list, chk_data):
assert(len(chk_data) >= len(cmd_list))
if is_del:
chk_data = list(reversed(chk_data))
for idx, cmd in enumerate(cmd_list):
last_cmd = re.findall(r"-c\s+'([^']+)'\s*", cmd)[-1]
neg_cmd = False
if last_cmd.startswith('no '):
neg_cmd = True
last_cmd = last_cmd[len('no '):]
assert(last_cmd.startswith('bgp confederation peers '))
peer_set = set(last_cmd[len('bgp confederation peers '):].split())
if is_del or (len(chk_data) >= 3 and idx == 0):
assert(neg_cmd)
else:
assert(not neg_cmd)
assert(peer_set == chk_data[idx])
conf_cmd = 'configure terminal'
conf_bgp_cmd = lambda vrf, asn: [conf_cmd, 'router bgp %d vrf %s' % (asn, vrf)]
conf_no_bgp_cmd = lambda vrf, asn: [conf_cmd, 'no router bgp %d%s' % (asn, '' if vrf == 'default' else ' vrf %s' % vrf)]
conf_bgp_dft_cmd = lambda vrf, asn: conf_bgp_cmd(vrf, asn) + ['no bgp default ipv4-unicast']
conf_bgp_af_cmd = lambda vrf, asn, af: conf_bgp_cmd(vrf, asn) + ['address-family %s unicast' % af]
bgp_globals_data = [
CmdMapTestInfo('BGP_GLOBALS', 'default', {'local_asn': 100},
conf_bgp_dft_cmd('default', 100), False, conf_no_bgp_cmd('default', 100), None, None, None),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'router_id': '1.1.1.1'},
conf_bgp_cmd('default', 100) + ['{}bgp router-id 1.1.1.1']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'load_balance_mp_relax': 'true'},
conf_bgp_cmd('default', 100) + ['{}bgp bestpath as-path multipath-relax ']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'as_path_mp_as_set': 'true'},
conf_bgp_cmd('default', 100) + ['bgp bestpath as-path multipath-relax as-set'], False,
conf_bgp_cmd('default', 100) + ['bgp bestpath as-path multipath-relax ']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'always_compare_med': 'false'},
conf_bgp_cmd('default', 100) + ['no bgp always-compare-med']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'external_compare_router_id': 'true'},
conf_bgp_cmd('default', 100) + ['{}bgp bestpath compare-routerid']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'ignore_as_path_length': 'true'},
conf_bgp_cmd('default', 100) + ['{}bgp bestpath as-path ignore']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'graceful_restart_enable': 'true'},
conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'gr_restart_time': '10'},
conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart restart-time 10']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'gr_stale_routes_time': '20'},
conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart stalepath-time 20']),
CmdMapTestInfo('BGP_GLOBALS', 'default', {'gr_preserve_fw_state': 'true'},
conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart preserve-fw-state']),
CmdMapTestInfo('BGP_GLOBALS_AF', 'default|ipv4_unicast', {'ebgp_route_distance': '100',
'ibgp_route_distance': '115',
'local_route_distance': '238'},
conf_bgp_af_cmd('default', 100, 'ipv4') + ['{}distance bgp 100 115 238']),
CmdMapTestInfo('BGP_GLOBALS_AF', 'default|ipv6_unicast', {'advertise-all-vni': 'true'},
conf_bgp_af_cmd('default', 100, 'ipv6') + ['{}advertise-all-vni']),
CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'local_asn': 200},
conf_bgp_dft_cmd('Vrf_red', 200), False, conf_no_bgp_cmd('Vrf_red', 200), None, None, None),
CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'med_confed': 'true'},
conf_bgp_cmd('Vrf_red', 200) + ['{}bgp bestpath med confed']),
CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'confed_peers': ['2', '10', '5']},
hdl_confed_peers_cmd, True, None, [{'2', '10', '5'}]),
CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'confed_peers': ['10', '8']},
hdl_confed_peers_cmd, False, None, [{'2', '5'}, {'8'}, {'10', '8'}]),
CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'keepalive': '300', 'holdtime': '900'},
conf_bgp_cmd('Vrf_red', 200) + ['{}timers bgp 300 900']),
CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'max_med_admin': 'true', 'max_med_admin_val': '20'},
conf_bgp_cmd('Vrf_red', 200) + ['{}bgp max-med administrative 20']),
CmdMapTestInfo('BGP_GLOBALS_AF', 'Vrf_red|ipv4_unicast', {'import_vrf': 'Vrf_test'},
conf_bgp_af_cmd('Vrf_red', 200, 'ipv4') + ['{}import vrf Vrf_test']),
CmdMapTestInfo('BGP_GLOBALS_AF', 'Vrf_red|ipv6_unicast', {'import_vrf_route_map': 'test_map'},
conf_bgp_af_cmd('Vrf_red', 200, 'ipv6') + ['{}import vrf route-map test_map']),
]
@patch.dict('sys.modules', swsssdk = swsssdk_module_mock)
@patch('frrcfgd.frrcfgd.g_run_command')
def data_set_del_test(test_data, run_cmd):
from frrcfgd.frrcfgd import BGPConfigDaemon
daemon = BGPConfigDaemon()
data_buf = {}
# add data in list
for test in test_data:
run_cmd.reset_mock()
hdlr = [h for t, h in daemon.table_handler_list if t == test.table_name]
assert(len(hdlr) == 1)
CmdMapTestInfo.add_test_data(test)
hdlr[0](test.table_name, test.key, CmdMapTestInfo.get_test_data(test))
test.check_running_cmd(run_cmd, False)
# delete data in reverse direction
for test in reversed(test_data):
if test.no_del:
continue
run_cmd.reset_mock()
hdlr = [h for t, h in daemon.table_handler_list if t == test.table_name]
assert(len(hdlr) == 1)
CmdMapTestInfo.del_test_data(test)
hdlr[0](test.table_name, test.key, CmdMapTestInfo.get_test_data(test))
test.check_running_cmd(run_cmd, True)
def test_bgp_globals():
data_set_del_test(bgp_globals_data)

View File

@ -0,0 +1,234 @@
import socket
import pytest
from unittest.mock import MagicMock, NonCallableMagicMock, patch
swsssdk_module_mock = MagicMock(ConfigDBConnector = NonCallableMagicMock)
with patch.dict('sys.modules', swsssdk = swsssdk_module_mock):
from frrcfgd.frrcfgd import CachedDataWithOp
from frrcfgd.frrcfgd import BGPPeerGroup
from frrcfgd.frrcfgd import BGPKeyMapInfo
from frrcfgd.frrcfgd import BGPKeyMapList
from frrcfgd.frrcfgd import get_command_cmn
from frrcfgd.frrcfgd import CommunityList
from frrcfgd.frrcfgd import MatchPrefix
from frrcfgd.frrcfgd import MatchPrefixList
from frrcfgd.frrcfgd import AggregateAddr
from frrcfgd.frrcfgd import IpNextHop
from frrcfgd.frrcfgd import IpNextHopSet
def test_data_with_op():
data = CachedDataWithOp()
assert(data.data is None)
assert(data.op == CachedDataWithOp.OP_NONE)
data = CachedDataWithOp(10, CachedDataWithOp.OP_ADD)
assert(data.data == 10)
assert(data.op == CachedDataWithOp.OP_ADD)
def test_peer_group():
pg = BGPPeerGroup('Vrf_red')
assert(pg.vrf == 'Vrf_red')
assert(len(pg.ref_nbrs) == 0)
def test_command_map():
def cmd_hdlr():
pass
key_map1 = BGPKeyMapInfo('test command', cmd_hdlr, None)
assert(key_map1.daemons is None)
assert(key_map1.run_cmd == 'test command')
assert(key_map1.hdl_func == cmd_hdlr)
assert(key_map1.data is None)
key_map2 = BGPKeyMapInfo('[bgpd,ospfd]daemon command', None, 100)
assert(key_map2.daemons == ['bgpd', 'ospfd'])
assert(key_map2.run_cmd == 'daemon command')
assert(key_map2.hdl_func == get_command_cmn)
assert(key_map2.data == 100)
def get_cmd_map_list(attr_list, map_key = None):
map_list = []
for attr in attr_list:
tokens = attr[0].split('|', 1)
if len(tokens) == 2:
key = tokens[1]
else:
key = None
if map_key is not None and key is not None and map_key != key:
continue
cmd_hdlr = cmd_data = None
if len(attr) >= 4:
cmd_hdlr = attr[2]
cmd_data = attr[3]
elif len(attr) == 3:
cmd_data = attr[2]
map_list.append(BGPKeyMapInfo(attr[1], cmd_hdlr, cmd_data))
return map_list
def test_command_map_list():
def cmd_hdlr(num):
pass
map_list = [('abc', 'set attribute abc'),
('defg', 'system config', cmd_hdlr, 10),
('test', 'system test', [20, 30]),
('xyz', 'config test'),
('ip_cmd|ipv4', 'test on ipv4'),
('ip_cmd|ipv6', 'test on ipv6')]
cmd_map_list = BGPKeyMapList(map_list, 'frrcfg', {'ip_cmd': 'ipv4'})
chk_map_list = get_cmd_map_list(map_list, 'ipv4')
for idx, cmd_map in enumerate(cmd_map_list):
assert(chk_map_list[idx] == cmd_map[1])
cmd_map_list = BGPKeyMapList(map_list, 'frrcfg', {'ip_cmd': 'ipv6'})
chk_map_list = get_cmd_map_list(map_list, 'ipv6')
for idx, cmd_map in enumerate(cmd_map_list):
assert(chk_map_list[idx] == cmd_map[1])
def test_community_list():
for ext in [False, True]:
comm_list = CommunityList('comm', ext)
assert(comm_list.name == 'comm')
assert(comm_list.is_ext == ext)
assert(comm_list.match_action is None)
assert(comm_list.is_std is None)
assert(len(comm_list.mbr_list) == 0)
def test_match_prefix():
pfx = MatchPrefix(socket.AF_INET, '1.2.3.4/16')
assert(pfx.ip_prefix == '1.2.0.0/16')
assert(pfx.min_len is None)
assert(pfx.max_len is None)
assert(pfx.action == 'permit')
pfx = MatchPrefix(socket.AF_INET, '10.10.10.10/24', '25..29', 'deny')
assert(pfx.ip_prefix == '10.10.10.0/24')
assert(pfx.min_len == 25)
assert(pfx.max_len == 29)
assert(pfx.action == 'deny')
pfx = MatchPrefix(socket.AF_INET, '100.0.0.0/8', '16..32')
assert(pfx.ip_prefix == '100.0.0.0/8')
assert(pfx.min_len == 16)
assert(pfx.max_len is None)
assert(pfx.action == 'permit')
pfx = MatchPrefix(socket.AF_INET, '20.20.20.20/28', '25..30', 'deny')
assert(pfx.ip_prefix == '20.20.20.16/28')
assert(pfx.min_len is None)
assert(pfx.max_len == 30)
assert(pfx.action == 'deny')
pfx = MatchPrefix(socket.AF_INET6, '1:2::3:4/64')
assert(pfx.ip_prefix == '1:2::/64')
assert(pfx.min_len is None)
assert(pfx.max_len is None)
assert(pfx.action == 'permit')
pfx = MatchPrefix(socket.AF_INET6, '10:10::10:10/64', '70..100', 'deny')
assert(pfx.ip_prefix == '10:10::/64')
assert(pfx.min_len == 70)
assert(pfx.max_len == 100)
assert(pfx.action == 'deny')
pfx = MatchPrefix(socket.AF_INET6, '1001::/16', '16..128')
assert(pfx.ip_prefix == '1001::/16')
assert(pfx.min_len is None)
assert(pfx.max_len == 128)
assert(pfx.action == 'permit')
def test_match_prefix_list():
ipv4_pfx_attrs = [('10.1.1.1/16', '18..24', 'permit'),
('20.2.2.2/24', None, 'deny'),
('30.3.3.3/8', '10..32', 'permit'),
('40.4.4.4/28', '20..30', 'deny')]
ipv6_pfx_attrs = [('1000:1::1/64', '80..120', 'permit'),
('2000:2::2/96', None, 'deny'),
('3000:3::3/32', '40..128', 'permit'),
('4000:4::4/80', '60..100', 'deny')]
pfx_list = MatchPrefixList()
for attr in ipv4_pfx_attrs:
pfx_list.add_prefix(*attr)
assert(pfx_list.af == socket.AF_INET)
assert(len(pfx_list) == len(ipv4_pfx_attrs))
chk_pfx_list = []
for attr in ipv4_pfx_attrs:
chk_pfx_list.append(MatchPrefix(socket.AF_INET, *attr))
assert(all([x == y for x, y in zip(chk_pfx_list, pfx_list)]))
pfx_list = MatchPrefixList()
for attr in ipv6_pfx_attrs:
pfx_list.add_prefix(*attr)
assert(pfx_list.af == socket.AF_INET6)
assert(len(pfx_list) == len(ipv6_pfx_attrs))
chk_pfx_list = []
for attr in ipv6_pfx_attrs:
chk_pfx_list.append(MatchPrefix(socket.AF_INET6, *attr))
assert(all([x == y for x, y in zip(chk_pfx_list, pfx_list)]))
def test_match_prefix_list_fail():
pfx_list = MatchPrefixList()
pfx_list.add_prefix('1.2.3.0/24')
with pytest.raises(ValueError):
pfx_list.add_prefix('1::/64')
def test_aggregate_address():
addr = AggregateAddr()
assert(addr.as_set == False)
assert(addr.summary_only == False)
def test_ip_nexthop():
for af in [socket.AF_INET, socket.AF_INET6]:
nh = IpNextHop(af, None, None, None, 'Loopback0', None, None, None)
assert(nh.af == af)
assert(nh.blackhole == 'false')
assert(nh.ip == ('0.0.0.0' if af == socket.AF_INET else '::'))
assert(nh.track == 0)
assert(nh.interface == 'Loopback0')
assert(nh.tag == 0)
assert(nh.distance == 0)
assert(nh.nh_vrf == '')
arg_list = nh.get_arg_list()
assert(arg_list == ['false', '', 'Loopback0'] + [''] * 4)
nh = IpNextHop(af, 'true', '1.1.1.1' if af == socket.AF_INET else '1::1',
1, 'Ethernet0', 100, 2, 'default')
assert(nh.blackhole == 'true')
assert(nh.ip == ('0.0.0.0' if af == socket.AF_INET else '::'))
assert(nh.track == 1)
assert(nh.interface == '')
assert(nh.tag == 100)
assert(nh.distance == 2)
assert(nh.nh_vrf == '')
arg_list = nh.get_arg_list()
assert(arg_list == ['true', '', '', '1', '100', '2', ''])
nh = IpNextHop(socket.AF_INET, 'false', '1.2.3.4', 5, 'Ethernet1', 2345, 3, 'Vrf_red')
assert(nh.af == socket.AF_INET)
assert(nh.blackhole == 'false')
assert(nh.ip == '1.2.3.4')
assert(nh.track == 5)
assert(nh.interface == 'Ethernet1')
assert(nh.tag == 2345)
assert(nh.distance == 3)
assert(nh.nh_vrf == 'Vrf_red')
arg_list = nh.get_arg_list()
assert(arg_list == ['false', '1.2.3.4', 'Ethernet1', '5', '2345', '3', 'Vrf_red'])
nh = IpNextHop(socket.AF_INET6, 'false', '1001:1::2002', 6, 'Ethernet2', 9000, 4, 'Vrf_blue')
assert(nh.af == socket.AF_INET6)
assert(nh.blackhole == 'false')
assert(nh.ip == '1001:1::2002')
assert(nh.track == 6)
assert(nh.interface == 'Ethernet2')
assert(nh.tag == 9000)
assert(nh.distance == 4)
assert(nh.nh_vrf == 'Vrf_blue')
arg_list = nh.get_arg_list()
assert(arg_list == ['false', '1001:1::2002', 'Ethernet2', '6', '9000', '4', 'Vrf_blue'])
def test_nexthop_set():
for af in [socket.AF_INET, socket.AF_INET6]:
nh_set = IpNextHopSet(af)
bkh_list = ['false', 'false', 'false', 'true']
ip_list = ['1.1.1.1', '2.2.2.2', '3.3.3.3', None]
ip6_list = ['1::1', '2::2', '3::3', None]
intf_list = [None, 'Vlan0', 'Loopback1', None]
tag_list = [1000, 2000, 3000, 4000]
vrf_list = ['default', 'Vrf_red', 'Vrf_blue', None]
nh_set = IpNextHopSet(af, bkh_list, ip_list if af == socket.AF_INET else ip6_list, None,
intf_list, tag_list, None, vrf_list)
test_set = set()
for idx in range(len(ip_list)):
test_set.add(IpNextHop(af, bkh_list[idx], ip_list[idx] if af == socket.AF_INET else ip6_list[idx],
None, intf_list[idx], tag_list[idx], None, vrf_list[idx]))
assert(nh_set == test_set)