diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/instance.conf.j2
new file mode 100644
index 000000000000..e4ee9bf2eefd
--- /dev/null
+++ b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/instance.conf.j2
@@ -0,0 +1,35 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor {{ neighbor_addr }} peer-group VOQ_CHASSIS_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'] | default("60") }} {{ bgp_session['holdtime'] | default("180") }}
+{% endif %}
+!
+{% if 'admin_status' in bgp_session and bgp_session['admin_status'] == 'down' or 'admin_status' not in bgp_session and 'default_bgp_status' in CONFIG_DB__DEVICE_METADATA['localhost'] and CONFIG_DB__DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %}
+ neighbor {{ neighbor_addr }} shutdown
+{% endif %}
+!
+ address-family ipv4
+{% if constants.bgp.maximum_paths.enabled is defined and constants.bgp.maximum_paths.enabled %}
+ maximum-paths ibgp {{ constants.bgp.maximum_paths.ipv4 | default(64) }}
+{% endif %}
+!
+ exit-address-family
+!
+ address-family ipv6
+{% if constants.bgp.maximum_paths.enabled is defined and constants.bgp.maximum_paths.enabled %}
+ maximum-paths ibgp {{ constants.bgp.maximum_paths.ipv6 | default(64) }}
+{% endif %}
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/peer-group.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/peer-group.conf.j2
new file mode 100644
index 000000000000..8266c0c82d7f
--- /dev/null
+++ b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/peer-group.conf.j2
@@ -0,0 +1,23 @@
+!
+! template: bgpd/templates/voq_chassis/peer-group.conf.j2
+!
+ neighbor VOQ_CHASSIS_PEER peer-group
+ address-family ipv4
+{% if CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
+ neighbor VOQ_CHASSIS_PEER allowas-in 1
+{% endif %}
+ neighbor VOQ_CHASSIS_PEER activate
+ neighbor VOQ_CHASSIS_PEER addpath-tx-all-paths
+ neighbor VOQ_CHASSIS_PEER soft-reconfiguration inbound
+ exit-address-family
+ address-family ipv6
+{% if CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
+ neighbor VOQ_CHASSIS_PEER allowas-in 1
+{% endif %}
+ neighbor VOQ_CHASSIS_PEER activate
+ neighbor VOQ_CHASSIS_PEER addpath-tx-all-paths
+ neighbor VOQ_CHASSIS_PEER soft-reconfiguration inbound
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/peer-group.conf.j2
+!
diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2
new file mode 100644
index 000000000000..4c853d4f3220
--- /dev/null
+++ b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2
@@ -0,0 +1,7 @@
+!
+! template: bgpd/templates/voq_chassis/policies.conf.j2
+!
+!
+!
+! end of template: bgpd/templates/voq_chassis/policies.conf.j2
+!
diff --git a/files/image_config/constants/constants.yml b/files/image_config/constants/constants.yml
index 86179aee430e..94f3d0e9706c 100644
--- a/files/image_config/constants/constants.yml
+++ b/files/image_config/constants/constants.yml
@@ -54,3 +54,7 @@ constants:
db_table: "BGP_PEER_RANGE"
peer_group: "BGP_SPEAKER"
template_dir: "dynamic"
+ voq_chassis: # peer_type
+ enabled: true
+ db_table: "BGP_VOQ_CHASSIS_NEIGHBOR"
+ template_dir: "voq_chassis"
diff --git a/src/sonic-bgpcfgd/bgpcfgd/main.py b/src/sonic-bgpcfgd/bgpcfgd/main.py
index 360b54dc11aa..59ec3ac9ffbe 100644
--- a/src/sonic-bgpcfgd/bgpcfgd/main.py
+++ b/src/sonic-bgpcfgd/bgpcfgd/main.py
@@ -42,6 +42,7 @@ def do_work():
InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME),
InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VLAN_INTF_TABLE_NAME),
InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_LAG_INTF_TABLE_NAME),
+ InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VOQ_INBAND_INTERFACE_TABLE_NAME),
# State DB managers
ZebraSetSrc(common_objs, "STATE_DB", swsscommon.STATE_INTERFACE_TABLE_NAME),
# Peer Managers
@@ -49,6 +50,7 @@ def do_work():
BGPPeerMgrBase(common_objs, "CONFIG_DB", swsscommon.CFG_BGP_INTERNAL_NEIGHBOR_TABLE_NAME, "internal", False),
BGPPeerMgrBase(common_objs, "CONFIG_DB", "BGP_MONITORS", "monitors", False),
BGPPeerMgrBase(common_objs, "CONFIG_DB", "BGP_PEER_RANGE", "dynamic", False),
+ BGPPeerMgrBase(common_objs, "CONFIG_DB", "BGP_VOQ_CHASSIS_NEIGHBOR", "voq_chassis", False),
# AllowList Managers
BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES"),
# BBR Manager
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_all.json
new file mode 100644
index 000000000000..09f3274cc7d9
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_all.json
@@ -0,0 +1,22 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {}
+ },
+ "neighbor_addr": "10.10.10.10",
+ "bgp_session": {
+ "asn": "555",
+ "name": "internal1",
+ "keepalive": "5",
+ "holdtime": "30",
+ "admin_status": "down"
+ },
+ "constants": {
+ "bgp": {
+ "maximum_paths": {
+ "enabled": "true",
+ "ipv4": "32",
+ "ipv6": "24"
+ }
+ }
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_base.json
new file mode 100644
index 000000000000..53ad6ba68ead
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_base.json
@@ -0,0 +1,17 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {}
+ },
+ "neighbor_addr": "10.10.10.10",
+ "bgp_session": {
+ "asn": "555",
+ "name": "internal1"
+ },
+ "constants": {
+ "bgp": {
+ "maximum_paths": {
+ "enabled": "true"
+ }
+ }
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_shutdown_1.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_shutdown_1.json
new file mode 100644
index 000000000000..920c92dde708
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_shutdown_1.json
@@ -0,0 +1,19 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {
+ "default_bgp_status": "down"
+ }
+ },
+ "neighbor_addr": "10.10.10.10",
+ "bgp_session": {
+ "asn": "555",
+ "name": "internal1"
+ },
+ "constants": {
+ "bgp": {
+ "maximum_paths": {
+ "enabled": "true"
+ }
+ }
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_shutdown_2.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_shutdown_2.json
new file mode 100644
index 000000000000..872f5f7d3905
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_shutdown_2.json
@@ -0,0 +1,19 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {
+ "default_bgp_status": "up"
+ }
+ },
+ "neighbor_addr": "10.10.10.10",
+ "bgp_session": {
+ "asn": "555",
+ "name": "internal1"
+ },
+ "constants": {
+ "bgp": {
+ "maximum_paths": {
+ "enabled": "true"
+ }
+ }
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_timers_1.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_timers_1.json
new file mode 100644
index 000000000000..642aafcc69bf
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_timers_1.json
@@ -0,0 +1,18 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {}
+ },
+ "neighbor_addr": "10.10.10.10",
+ "bgp_session": {
+ "asn": "555",
+ "name": "internal1",
+ "keepalive": "5"
+ },
+ "constants": {
+ "bgp": {
+ "maximum_paths": {
+ "enabled": "true"
+ }
+ }
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_timers_2.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_timers_2.json
new file mode 100644
index 000000000000..48a046c34735
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/param_timers_2.json
@@ -0,0 +1,18 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {}
+ },
+ "neighbor_addr": "10.10.10.10",
+ "bgp_session": {
+ "asn": "555",
+ "name": "internal1",
+ "holdtime": "240"
+ },
+ "constants": {
+ "bgp": {
+ "maximum_paths": {
+ "enabled": "true"
+ }
+ }
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_all.conf
new file mode 100644
index 000000000000..0f15d2f7f3e9
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_all.conf
@@ -0,0 +1,23 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor 10.10.10.10 peer-group VOQ_CHASSIS_PEER
+ neighbor 10.10.10.10 remote-as 555
+ neighbor 10.10.10.10 description internal1
+ neighbor 10.10.10.10 timers 5 30
+ neighbor 10.10.10.10 shutdown
+ address-family ipv4
+ maximum-paths ibgp 32
+!
+ exit-address-family
+!
+ address-family ipv6
+ maximum-paths ibgp 24
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_base.conf
new file mode 100644
index 000000000000..c15098c782a9
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_base.conf
@@ -0,0 +1,21 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor 10.10.10.10 peer-group VOQ_CHASSIS_PEER
+ neighbor 10.10.10.10 remote-as 555
+ neighbor 10.10.10.10 description internal1
+ address-family ipv4
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+ address-family ipv6
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_shutdown_1.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_shutdown_1.conf
new file mode 100644
index 000000000000..6b929baf8759
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_shutdown_1.conf
@@ -0,0 +1,22 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor 10.10.10.10 peer-group VOQ_CHASSIS_PEER
+ neighbor 10.10.10.10 remote-as 555
+ neighbor 10.10.10.10 description internal1
+ neighbor 10.10.10.10 shutdown
+ address-family ipv4
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+ address-family ipv6
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_shutdown_2.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_shutdown_2.conf
new file mode 100644
index 000000000000..c15098c782a9
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_shutdown_2.conf
@@ -0,0 +1,21 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor 10.10.10.10 peer-group VOQ_CHASSIS_PEER
+ neighbor 10.10.10.10 remote-as 555
+ neighbor 10.10.10.10 description internal1
+ address-family ipv4
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+ address-family ipv6
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_timers_1.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_timers_1.conf
new file mode 100644
index 000000000000..f7feab971f8a
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_timers_1.conf
@@ -0,0 +1,22 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor 10.10.10.10 peer-group VOQ_CHASSIS_PEER
+ neighbor 10.10.10.10 remote-as 555
+ neighbor 10.10.10.10 description internal1
+ neighbor 10.10.10.10 timers 5 180
+ address-family ipv4
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+ address-family ipv6
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_timers_2.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_timers_2.conf
new file mode 100644
index 000000000000..8e773c113b3d
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/instance.conf/result_timers_2.conf
@@ -0,0 +1,22 @@
+!
+! template: bgpd/templates/voq_chassis/instance.conf.j2
+!
+ bgp bestpath as-path multipath-relax
+ bgp bestpath peer-type multipath-relax
+!
+ neighbor 10.10.10.10 peer-group VOQ_CHASSIS_PEER
+ neighbor 10.10.10.10 remote-as 555
+ neighbor 10.10.10.10 description internal1
+ neighbor 10.10.10.10 timers 60 240
+ address-family ipv4
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+ address-family ipv6
+ maximum-paths ibgp 64
+!
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/instance.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/param_all.json
new file mode 100644
index 000000000000..293ccc7990dc
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/param_all.json
@@ -0,0 +1,7 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {
+ "type": "ToRRouter"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/param_base.json
new file mode 100644
index 000000000000..7ef21c181d7e
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/param_base.json
@@ -0,0 +1,5 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {}
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/result_all.conf
new file mode 100644
index 000000000000..031884499aaa
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/result_all.conf
@@ -0,0 +1,19 @@
+!
+! template: bgpd/templates/voq_chassis/peer-group.conf.j2
+!
+ neighbor VOQ_CHASSIS_PEER peer-group
+ address-family ipv4
+ neighbor VOQ_CHASSIS_PEER allowas-in 1
+ neighbor VOQ_CHASSIS_PEER activate
+ neighbor VOQ_CHASSIS_PEER addpath-tx-all-paths
+ neighbor VOQ_CHASSIS_PEER soft-reconfiguration inbound
+ exit-address-family
+ address-family ipv6
+ neighbor VOQ_CHASSIS_PEER allowas-in 1
+ neighbor VOQ_CHASSIS_PEER activate
+ neighbor VOQ_CHASSIS_PEER addpath-tx-all-paths
+ neighbor VOQ_CHASSIS_PEER soft-reconfiguration inbound
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/peer-group.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/result_base.conf
new file mode 100644
index 000000000000..d4a6f381a224
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/peer-group.conf/result_base.conf
@@ -0,0 +1,17 @@
+!
+! template: bgpd/templates/voq_chassis/peer-group.conf.j2
+!
+ neighbor VOQ_CHASSIS_PEER peer-group
+ address-family ipv4
+ neighbor VOQ_CHASSIS_PEER activate
+ neighbor VOQ_CHASSIS_PEER addpath-tx-all-paths
+ neighbor VOQ_CHASSIS_PEER soft-reconfiguration inbound
+ exit-address-family
+ address-family ipv6
+ neighbor VOQ_CHASSIS_PEER activate
+ neighbor VOQ_CHASSIS_PEER addpath-tx-all-paths
+ neighbor VOQ_CHASSIS_PEER soft-reconfiguration inbound
+ exit-address-family
+!
+! end of template: bgpd/templates/voq_chassis/peer-group.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json
new file mode 100644
index 000000000000..7ef21c181d7e
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json
@@ -0,0 +1,5 @@
+{
+ "CONFIG_DB__DEVICE_METADATA": {
+ "localhost": {}
+ }
+}
diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf
new file mode 100644
index 000000000000..4c853d4f3220
--- /dev/null
+++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf
@@ -0,0 +1,7 @@
+!
+! template: bgpd/templates/voq_chassis/policies.conf.j2
+!
+!
+!
+! end of template: bgpd/templates/voq_chassis/policies.conf.j2
+!
diff --git a/src/sonic-bgpcfgd/tests/test_templates.py b/src/sonic-bgpcfgd/tests/test_templates.py
index 7d3bc773ad16..23ada1aaf3f6 100644
--- a/src/sonic-bgpcfgd/tests/test_templates.py
+++ b/src/sonic-bgpcfgd/tests/test_templates.py
@@ -140,3 +140,15 @@ def test_monitors_pg():
def test_monitors_instance():
test_data = load_tests("monitors", "instance.conf")
run_tests("monitors_instance", *test_data)
+
+def test_voq_chassis_policies():
+ test_data = load_tests("voq_chassis", "policies.conf")
+ run_tests("voq_chassis_policies", *test_data)
+
+def test_voq_chassis_pg():
+ test_data = load_tests("voq_chassis", "peer-group.conf")
+ run_tests("voq_chassis_pg", *test_data)
+
+def test_voq_chassis_instance():
+ test_data = load_tests("voq_chassis", "instance.conf")
+ run_tests("voq_chassis_instance", *test_data)
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 06b799cdeff7..93b92c9abd48 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -675,6 +675,7 @@ def parse_host_loopback(dpg, hname):
def parse_cpg(cpg, hname, local_devices=[]):
bgp_sessions = {}
bgp_internal_sessions = {}
+ bgp_voq_chassis_sessions = {}
myasn = None
bgp_peers_with_range = {}
for child in cpg:
@@ -696,46 +697,40 @@ def parse_cpg(cpg, hname, local_devices=[]):
keepalive = 60
nhopself = 1 if session.find(str(QName(ns, "NextHopSelf"))) is not None else 0
+ # choose the right table and admin_status for the peer
+ voq_chassis = session.find(str(QName(ns, "VoQChassisInternal")))
+ if voq_chassis is not None and voq_chassis.text == "true":
+ table = bgp_voq_chassis_sessions
+ admin_status = 'up'
+ elif end_router.lower() in local_devices and start_router.lower() in local_devices:
+ table = bgp_internal_sessions
+ admin_status = 'up'
+ else:
+ table = bgp_sessions
+ admin_status = None
+
if end_router.lower() == hname.lower():
- if end_router.lower() in local_devices and start_router.lower() in local_devices:
- bgp_internal_sessions[start_peer.lower()] = {
- 'name': start_router,
- 'local_addr': end_peer.lower(),
- 'rrclient': rrclient,
- 'holdtime': holdtime,
- 'keepalive': keepalive,
- 'nhopself': nhopself,
- 'admin_status': 'up'
- }
- else:
- bgp_sessions[start_peer.lower()] = {
- 'name': start_router,
- 'local_addr': end_peer.lower(),
- 'rrclient': rrclient,
- 'holdtime': holdtime,
- 'keepalive': keepalive,
- 'nhopself': nhopself
- }
+ table[start_peer.lower()] = {
+ 'name': start_router,
+ 'local_addr': end_peer.lower(),
+ 'rrclient': rrclient,
+ 'holdtime': holdtime,
+ 'keepalive': keepalive,
+ 'nhopself': nhopself
+ }
+ if admin_status:
+ table[start_peer.lower()]['admin_status'] = admin_status
elif start_router.lower() == hname.lower():
- if end_router.lower() in local_devices and start_router.lower() in local_devices:
- bgp_internal_sessions[end_peer.lower()] = {
- 'name': end_router,
- 'local_addr': start_peer.lower(),
- 'rrclient': rrclient,
- 'holdtime': holdtime,
- 'keepalive': keepalive,
- 'nhopself': nhopself,
- 'admin_status': 'up'
- }
- else:
- bgp_sessions[end_peer.lower()] = {
- 'name': end_router,
- 'local_addr': start_peer.lower(),
- 'rrclient': rrclient,
- 'holdtime': holdtime,
- 'keepalive': keepalive,
- 'nhopself': nhopself
- }
+ table[end_peer.lower()] = {
+ 'name': end_router,
+ 'local_addr': start_peer.lower(),
+ 'rrclient': rrclient,
+ 'holdtime': holdtime,
+ 'keepalive': keepalive,
+ 'nhopself': nhopself
+ }
+ if admin_status:
+ table[end_peer.lower()]['admin_status'] = admin_status
elif child.tag == str(QName(ns, "Routers")):
for router in child.findall(str(QName(ns1, "BGPRouterDeclaration"))):
asn = router.find(str(QName(ns1, "ASN"))).text
@@ -766,12 +761,19 @@ def parse_cpg(cpg, hname, local_devices=[]):
bgp_internal_session = bgp_internal_sessions[peer]
if hostname.lower() == bgp_internal_session['name'].lower():
bgp_internal_session['asn'] = asn
+ for peer in bgp_voq_chassis_sessions:
+ bgp_session = bgp_voq_chassis_sessions[peer]
+ if hostname.lower() == bgp_session['name'].lower():
+ bgp_session['asn'] = asn
bgp_monitors = { key: bgp_sessions[key] for key in bgp_sessions if 'asn' in bgp_sessions[key] and bgp_sessions[key]['name'] == 'BGPMonitor' }
- bgp_sessions = { key: bgp_sessions[key] for key in bgp_sessions if 'asn' in bgp_sessions[key] and int(bgp_sessions[key]['asn']) != 0 }
- bgp_internal_sessions = { key: bgp_internal_sessions[key] for key in bgp_internal_sessions if 'asn' in bgp_internal_sessions[key] and int(bgp_internal_sessions[key]['asn']) != 0 }
+ def filter_bad_asn(table):
+ return { key: table[key] for key in table if 'asn' in table[key] and int(table[key]['asn']) != 0 }
+ bgp_sessions = filter_bad_asn(bgp_sessions)
+ bgp_internal_sessions = filter_bad_asn(bgp_internal_sessions)
+ bgp_voq_chassis_sessions = filter_bad_asn(bgp_voq_chassis_sessions)
- return bgp_sessions, bgp_internal_sessions, myasn, bgp_peers_with_range, bgp_monitors
+ return bgp_sessions, bgp_internal_sessions, bgp_voq_chassis_sessions, myasn, bgp_peers_with_range, bgp_monitors
def parse_meta(meta, hname):
@@ -1138,7 +1140,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
if child.tag == str(QName(ns, "DpgDec")):
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
- (bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname)
+ (bgp_sessions, bgp_internal_sessions, bgp_voq_chassis_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
(neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content) = parse_png(child, hostname, dpg_ecmp_content)
elif child.tag == str(QName(ns, "UngDec")):
@@ -1154,7 +1156,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, asic_name)
host_lo_intfs = parse_host_loopback(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
- (bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name, local_devices)
+ (bgp_sessions, bgp_internal_sessions, bgp_voq_chassis_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name, local_devices)
elif child.tag == str(QName(ns, "PngDec")):
(neighbors, devices, port_speed_png) = parse_asic_png(child, asic_name, hostname)
elif child.tag == str(QName(ns, "MetadataDeclaration")):
@@ -1223,6 +1225,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
results['BGP_MONITORS'] = bgp_monitors
results['BGP_PEER_RANGE'] = bgp_peers_with_range
results['BGP_INTERNAL_NEIGHBOR'] = bgp_internal_sessions
+ results['BGP_VOQ_CHASSIS_NEIGHBOR'] = bgp_voq_chassis_sessions
if mgmt_routes:
# TODO: differentiate v4 and v6
next(iter(mgmt_intf.values()))['forced_mgmt_routes'] = mgmt_routes
diff --git a/src/sonic-config-engine/tests/simple-sample-graph.xml b/src/sonic-config-engine/tests/simple-sample-graph.xml
index 7215209da545..c7c27ed2b8c6 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph.xml
@@ -20,6 +20,7 @@
1
180
60
+ false
switch-t0
@@ -49,6 +50,26 @@
180
60
+
+ switch-t0
+ FC00::75
+ ARISTA02T1
+ FC00::76
+ 1
+ 180
+ 60
+
+
+ false
+ switch-t0
+ 10.2.0.20
+ CHASSIS_PEER
+ 10.2.0.21
+ 1
+ 180
+ 60
+ true
+
@@ -82,6 +103,12 @@
+
+ 10.2.0.21
+
+
+
+
@@ -105,6 +132,11 @@
ARISTA04T1
+
+ 65100
+ CHASSIS_PEER
+
+
diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py
index 3a85346de2fd..f67f4ed0b520 100644
--- a/src/sonic-config-engine/tests/test_cfggen.py
+++ b/src/sonic-config-engine/tests/test_cfggen.py
@@ -490,6 +490,19 @@ def test_minigraph_bgp_mon(self):
utils.to_dict("{'10.20.30.40': {'rrclient': 0, 'name': 'BGPMonitor', 'local_addr': '10.1.0.32', 'nhopself': 0, 'holdtime': '10', 'asn': '0', 'keepalive': '3'}}")
)
+ def test_minigraph_bgp_voq_chassis_peer(self):
+ argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "BGP_VOQ_CHASSIS_NEIGHBOR[\'10.2.0.21\']"'
+ output = self.run_script(argument)
+ self.assertEqual(
+ utils.to_dict(output.strip()),
+ utils.to_dict("{'rrclient': 0, 'name': 'CHASSIS_PEER', 'local_addr': '10.2.0.20', 'nhopself': 0, 'holdtime': '180', 'asn': '65100', 'keepalive': '60', 'admin_status': 'up'}")
+ )
+
+ # make sure VoQChassisInternal value of false is honored
+ argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "BGP_VOQ_CHASSIS_NEIGHBOR[\'10.0.0.57\']"'
+ output = self.run_script(argument)
+ self.assertEqual(output.strip(), "")
+
def test_minigraph_sub_port_interfaces(self, check_stderr=True):
try:
print('\n Change device type to %s' % (BACKEND_TOR_ROUTER))