Skip to content

Commit 3bffc2a

Browse files
lguohanMichelMoriniaux
authored andcommitted
[docker-frr]: bring quagga docker features to frr docker (sonic-net#2870)
- use superviord to manage process in frr docker - intro separated configuration mode for frr - bring quagga configuration template to frr. Signed-off-by: Guohan Lu <[email protected]>
1 parent 354bb49 commit 3bffc2a

File tree

10 files changed

+394
-100
lines changed

10 files changed

+394
-100
lines changed

dockers/docker-fpm-frr/Dockerfile.j2

+4-8
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ RUN apt-get autoclean -y
3636
RUN apt-get autoremove -y
3737
RUN rm -rf /debs ~/.cache
3838

39+
COPY ["bgpcfgd", "start.sh", "/usr/bin/"]
3940
COPY ["*.j2", "/usr/share/sonic/templates/"]
40-
COPY ["start.sh", "config.sh", "/usr/bin/"]
41-
COPY ["daemons", "/etc/frr/"]
42-
COPY ["daemons.conf", "/etc/frr/"]
43-
COPY ["vtysh.conf", "/etc/frr/"]
44-
45-
ENTRYPOINT /usr/bin/config.sh \
46-
&& /usr/bin/start.sh \
47-
&& /bin/bash
41+
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
42+
43+
ENTRYPOINT ["/usr/bin/supervisord"]

dockers/docker-fpm-frr/bgpcfgd

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env python
2+
3+
import sys
4+
import redis
5+
import subprocess
6+
import syslog
7+
from swsssdk import ConfigDBConnector
8+
9+
class BGPConfigDaemon:
10+
11+
def __init__(self):
12+
self.config_db = ConfigDBConnector()
13+
self.config_db.connect()
14+
self.bgp_asn = self.config_db.get_entry('DEVICE_METADATA', 'localhost')['bgp_asn']
15+
self.bgp_neighbor = self.config_db.get_table('BGP_NEIGHBOR')
16+
17+
def __run_command(self, command):
18+
# print command
19+
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
20+
stdout = p.communicate()[0]
21+
p.wait()
22+
if p.returncode != 0:
23+
syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] command execution returned {}. Command: "{}", stdout: "{}"'.format(p.returncode, command, stdout))
24+
25+
def metadata_handler(self, key, data):
26+
if key == 'localhost' and data.has_key('bgp_asn'):
27+
if data['bgp_asn'] != self.bgp_asn:
28+
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] ASN changed to {} from {}, restart BGP...'.format(data['bgp_asn'], self.bgp_asn))
29+
self.__run_command("supervisorctl restart start.sh")
30+
self.__run_command("service quagga restart")
31+
self.bgp_asn = data['bgp_asn']
32+
33+
def bgp_handler(self, key, data):
34+
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] value for {} changed to {}'.format(key, data))
35+
if not data:
36+
# Neighbor is deleted
37+
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {}'".format(self.bgp_asn, key)
38+
self.__run_command(command)
39+
self.bgp_neighbor.pop(key)
40+
else:
41+
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} remote-as {}'".format(self.bgp_asn, key, data['asn'])
42+
self.__run_command(command)
43+
if data.has_key('name'):
44+
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} description {}'".format(self.bgp_asn, key, data['name'])
45+
self.__run_command(command)
46+
if data.has_key('admin_status'):
47+
command_mod = 'no ' if data['admin_status'] == 'up' else ''
48+
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c '{}neighbor {} shutdown'".format(self.bgp_asn, command_mod, key)
49+
self.__run_command(command)
50+
self.bgp_neighbor[key] = data
51+
52+
def start(self):
53+
self.config_db.subscribe('BGP_NEIGHBOR',
54+
lambda table, key, data: self.bgp_handler(key, data))
55+
self.config_db.subscribe('DEVICE_METADATA',
56+
lambda table, key, data: self.metadata_handler(key, data))
57+
self.config_db.listen()
58+
59+
60+
def main():
61+
daemon = BGPConfigDaemon()
62+
daemon.start()
63+
64+
if __name__ == "__main__":
65+
main()

dockers/docker-fpm-frr/bgpd.conf.j2

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
!
2+
{% block banner %}
3+
! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
4+
! generated by templates/quagga/bgpd.conf.j2 with config DB data
5+
! file: bgpd.conf
6+
!
7+
{% endblock banner %}
8+
!
9+
{% block system_init %}
10+
hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
11+
password zebra
12+
log syslog informational
13+
log facility local4
14+
! enable password {# {{ en_passwd }} TODO: param needed #}
15+
{% endblock system_init %}
16+
!
17+
{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %}
18+
{% block bgp_init %}
19+
!
20+
! bgp multiple-instance
21+
!
22+
route-map FROM_BGP_SPEAKER_V4 permit 10
23+
!
24+
route-map TO_BGP_SPEAKER_V4 deny 10
25+
!
26+
router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
27+
bgp log-neighbor-changes
28+
bgp bestpath as-path multipath-relax
29+
no bgp default ipv4-unicast
30+
bgp graceful-restart restart-time 240
31+
bgp graceful-restart
32+
{% for (name, prefix) in LOOPBACK_INTERFACE %}
33+
{% if prefix | ipv4 and name == 'Loopback0' %}
34+
bgp router-id {{ prefix | ip }}
35+
{% endif %}
36+
{% endfor %}
37+
{# advertise loopback #}
38+
{% for (name, prefix) in LOOPBACK_INTERFACE %}
39+
{% if prefix | ipv4 and name == 'Loopback0' %}
40+
network {{ prefix | ip }}/32
41+
{% elif prefix | ipv6 and name == 'Loopback0' %}
42+
address-family ipv6
43+
network {{ prefix | ip }}/64
44+
exit-address-family
45+
{% endif %}
46+
{% endfor %}
47+
{% endblock bgp_init %}
48+
{% endif %}
49+
{% block vlan_advertisement %}
50+
{% for (name, prefix) in VLAN_INTERFACE %}
51+
{% if prefix | ipv4 %}
52+
network {{ prefix }}
53+
{% elif prefix | ipv6 %}
54+
address-family ipv6
55+
network {{ prefix }}
56+
exit-address-family
57+
{% endif %}
58+
{% endfor %}
59+
{% endblock vlan_advertisement %}
60+
{% block bgp_sessions %}
61+
{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %}
62+
{% if bgp_session['asn'] | int != 0 %}
63+
neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }}
64+
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
65+
{# set the bgp neighbor timers if they have not default values #}
66+
{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60)
67+
or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %}
68+
neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }}
69+
{% endif %}
70+
{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %}
71+
neighbor {{ neighbor_addr }} shutdown
72+
{% endif %}
73+
{% if neighbor_addr | ipv4 %}
74+
address-family ipv4
75+
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
76+
neighbor {{ neighbor_addr }} allowas-in 1
77+
{% endif %}
78+
neighbor {{ neighbor_addr }} activate
79+
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
80+
maximum-paths 64
81+
exit-address-family
82+
{% endif %}
83+
{% if neighbor_addr | ipv6 %}
84+
address-family ipv6
85+
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
86+
neighbor {{ neighbor_addr }} allowas-in 1
87+
{% endif %}
88+
neighbor {{ neighbor_addr }} activate
89+
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
90+
maximum-paths 64
91+
exit-address-family
92+
{% endif %}
93+
{% endif %}
94+
{% endfor %}
95+
{% endblock bgp_sessions %}
96+
{% block bgp_peers_with_range %}
97+
{% if BGP_PEER_RANGE %}
98+
{% for bgp_peer in BGP_PEER_RANGE.values() %}
99+
neighbor {{ bgp_peer['name'] }} peer-group
100+
neighbor {{ bgp_peer['name'] }} passive
101+
{% if bgp_peer['peer_asn'] is defined %}
102+
neighbor {{ bgp_peer['name'] }} remote-as {{ bgp_peer['peer_asn'] }}
103+
{% else %}
104+
neighbor {{ bgp_peer['name'] }} remote-as {{ deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']] }}
105+
{% endif %}
106+
neighbor {{ bgp_peer['name'] }} ebgp-multihop 255
107+
neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound
108+
{% if bgp_peer['src_address'] is defined %}
109+
neighbor {{ bgp_peer['name'] }} update-source {{ bgp_peer['src_address'] | ip }}
110+
{% else %}
111+
{% for (name, prefix) in LOOPBACK_INTERFACE %}
112+
{% if name == 'Loopback1' %}
113+
neighbor {{ bgp_peer['name'] }} update-source {{ prefix | ip }}
114+
{% endif %}
115+
{% endfor %}
116+
{% endif %}
117+
neighbor {{ bgp_peer['name'] }} route-map FROM_BGP_SPEAKER_V4 in
118+
neighbor {{ bgp_peer['name'] }} route-map TO_BGP_SPEAKER_V4 out
119+
{% for ip_range in bgp_peer['ip_range'] %}
120+
bgp listen range {{ip_range}} peer-group {{ bgp_peer['name'] }}
121+
{% endfor %}
122+
address-family ipv4
123+
neighbor {{ bgp_peer['name'] }} activate
124+
maximum-paths 64
125+
exit-address-family
126+
address-family ipv6
127+
neighbor {{ bgp_peer['name'] }} activate
128+
maximum-paths 64
129+
exit-address-family
130+
{% endfor %}
131+
{% endif %}
132+
{% endblock bgp_peers_with_range %}
133+
!
134+
{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %}
135+
maximum-paths 64
136+
!
137+
route-map ISOLATE permit 10
138+
set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
139+
{% endif %}
140+
!

dockers/docker-fpm-frr/config.sh

-20
This file was deleted.

dockers/docker-fpm-frr/daemons

-65
This file was deleted.

dockers/docker-fpm-frr/daemons.conf

-1
This file was deleted.

dockers/docker-fpm-frr/start.sh

+39-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,41 @@
1-
#!/bin/bash
1+
#!/usr/bin/env bash
2+
3+
mkdir -p /etc/frr
4+
5+
CONFIG_TYPE=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["docker_routing_config_mode"]'`
6+
7+
if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then
8+
sonic-cfggen -d -y /etc/sonic/deployment_id_asn_map.yml -t /usr/share/sonic/templates/bgpd.conf.j2 > /etc/frr/bgpd.conf
9+
sonic-cfggen -d -t /usr/share/sonic/templates/zebra.conf.j2 > /etc/frr/zebra.conf
10+
touch /etc/frr/vtysh.conf
11+
elif [ "$CONFIG_TYPE" == "unified" ]; then
12+
sonic-cfggen -d -y /etc/sonic/deployment_id_asn_map.yml -t /usr/share/sonic/templates/frr.conf.j2 >/etc/frr/frr.conf
13+
echo "service integrated-vtysh-config" > /etc/frr/vtysh.conf
14+
fi
15+
16+
sonic-cfggen -d -t /usr/share/sonic/templates/isolate.j2 > /usr/sbin/bgp-isolate
17+
chown root:root /usr/sbin/bgp-isolate
18+
chmod 0755 /usr/sbin/bgp-isolate
19+
20+
sonic-cfggen -d -t /usr/share/sonic/templates/unisolate.j2 > /usr/sbin/bgp-unisolate
21+
chown root:root /usr/sbin/bgp-unisolate
22+
chmod 0755 /usr/sbin/bgp-unisolate
23+
24+
mkdir -p /var/sonic
25+
echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status
226

327
rm -f /var/run/rsyslogd.pid
4-
service rsyslog start
5-
service frr start
6-
fpmsyncd &
28+
29+
supervisorctl start rsyslogd
30+
31+
supervisorctl start bgpcfgd
32+
33+
# Start Quagga processes
34+
supervisorctl start zebra
35+
supervisorctl start bgpd
36+
37+
if [ "$CONFIG_TYPE" == "unified" ]; then
38+
supervisorctl start vtysh_b
39+
fi
40+
41+
supervisorctl start fpmsyncd

0 commit comments

Comments
 (0)