Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supports FRR-VRRP configuration #18617

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ program:zebra
program:staticd
program:bgpd
program:fpmsyncd
program:vrrpd
program:macvlanmgrd
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
program:bfdd
program:ospfd
Expand Down
23 changes: 23 additions & 0 deletions dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ dependent_startup=true
dependent_startup_wait_for=zebra:running
{% endif %}

[program:vrrpd]
command=/usr/lib/frr/vrrpd -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

[program:bgpd]
command=/usr/lib/frr/bgpd -A 127.0.0.1 -M snmp
priority=5
Expand Down Expand Up @@ -125,6 +137,17 @@ stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=bgpd:running

[program:macvlanmgrd]
command=macvlanmgrd
priority=6
autostart=false
autorestart=false
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=vrrpd: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
Expand Down
18 changes: 16 additions & 2 deletions files/image_config/copp/copp_cfg.j2
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,17 @@
"red_action": "drop",
"trap_action": "trap",
"trap_priority": "1"

}
},
"queue2_group2": {
"cir":"300",
"cbs":"300",
"meter_type":"packets",
"mode":"sr_tcm",
"red_action":"drop",
"trap_action":"trap",
"trap_priority":"7",
"queue": "7"
}
},
"COPP_TRAP": {
"bgp": {
Expand Down Expand Up @@ -118,6 +127,11 @@
"trap_ids": "src_nat_miss,dest_nat_miss",
"trap_group": "queue1_group2"
},
"vrrp": {
"trap_ids": "vrrp,vrrpv6",
"trap_group": "queue2_group2",
"always_enabled": "true"
},
"sflow": {
"trap_group": "queue2_group1",
"trap_ids": "sample_packet"
Expand Down
2 changes: 1 addition & 1 deletion rules/docker-fpm-frr.mk
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ SONIC_DOCKER_IMAGES += $(DOCKER_FPM_FRR)
SONIC_DOCKER_DBG_IMAGES += $(DOCKER_FPM_FRR_DBG)

$(DOCKER_FPM_FRR)_CONTAINER_NAME = bgp
$(DOCKER_FPM_FRR)_RUN_OPT += -t --cap-add=NET_ADMIN --cap-add=SYS_ADMIN
$(DOCKER_FPM_FRR)_RUN_OPT += -t --cap-add=NET_ADMIN --cap-add=SYS_ADMIN --cap-add=CAP_NET_ADMIN
$(DOCKER_FPM_FRR)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
$(DOCKER_FPM_FRR)_RUN_OPT += -v /etc/timezone:/etc/timezone:ro

Expand Down
242 changes: 241 additions & 1 deletion src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def extract_cmd_daemons(cmd_str):
class BgpdClientMgr(threading.Thread):
VTYSH_MARK = 'vtysh '
PROXY_SERVER_ADDR = '/etc/frr/bgpd_client_sock'
ALL_DAEMONS = ['bgpd', 'zebra', 'staticd', 'bfdd', 'ospfd', 'pimd']
ALL_DAEMONS = ['bgpd', 'zebra', 'staticd', 'bfdd', 'ospfd', 'pimd', 'vrrpd']
TABLE_DAEMON = {
'DEVICE_METADATA': ['bgpd'],
'BGP_GLOBALS': ['bgpd'],
Expand Down Expand Up @@ -118,6 +118,10 @@ class BgpdClientMgr(threading.Thread):
'PIM_INTERFACE': ['pimd'],
'IGMP_INTERFACE': ['pimd'],
'IGMP_INTERFACE_QUERY': ['pimd'],
'VRRP': ['vrrpd'],
'VRRP6': ['vrrpd'],
'VRRP_TRACK': ['vrrpd'],
'VRRP6_TRACK': ['vrrpd'],
}
VTYSH_CMD_DAEMON = [(r'show (ip|ipv6) route($|\s+\S+)', ['zebra']),
(r'show ip mroute($|\s+\S+)', ['pimd']),
Expand All @@ -132,6 +136,7 @@ class BgpdClientMgr(threading.Thread):
(r'show ip sla($|\s+\S+)', ['iptrackd']),
(r'clear ip sla($|\s+\S+)', ['iptrackd']),
(r'clear ip igmp($|\s+\S+)', ['pimd']),
(r'show vrrp($|\s+\S+)', ['vrrpd']),
(r'.*', ['bgpd'])]
@staticmethod
def __create_proxy_socket():
Expand Down Expand Up @@ -2240,6 +2245,10 @@ def __init__(self):
('BGP_GLOBALS_EVPN_RT', self.bgp_table_handler_common),
('BGP_GLOBALS_EVPN_VNI_RT', self.bgp_table_handler_common),
('BFD_PEER', self.bfd_handler),
('VRRP', self.vrrp_handler),
('VRRP6', self.vrrp6_handler),
('VRRP_TRACK', self.vrrp_track_handler),
('VRRP6_TRACK', self.vrrp6_track_handler),
('NEIGHBOR_SET', self.bgp_table_handler_common),
('NEXTHOP_SET', self.bgp_table_handler_common),
('TAG_SET', self.bgp_table_handler_common),
Expand Down Expand Up @@ -2338,6 +2347,237 @@ def bfd_handler(self, table, key, data):
command = command + " -c 'shutdown'"
self.__run_command(table, command)

def vrrp_handler(self, table, key, data):
syslog.syslog(syslog.LOG_INFO, '[vrrp cfgd](vrrp) value for {} changed to {}'.format(key, data))
#get frr vrrp session key
key_params = key.split('|')
intf_cmd = 'interface {}'.format(key_params[0])
cmd = 'vrrp {}'.format(key_params[1])
table_key = ExtConfigDBConnector.get_table_key(table, key)
comb_attr_list = ['vip']
if not data:
#VRRP instance is deleted
command = "vtysh -c 'configure terminal' -c '{}' -c 'no {}'".format(intf_cmd, cmd)
self.__run_command(table, command)
#del cache data
del(self.table_data_cache[table_key])
else:
#create/update case
command = "vtysh -c 'configure terminal' -c '{}'".format(intf_cmd)
self.__add_op_to_data(table_key, data, comb_attr_list)
cached_data = self.table_data_cache.setdefault(table_key, {})
for param in data:
if param == 'vid':
if param in cached_data and data[param].data == cached_data[param]:
continue
elif 'vip' not in data:
command = command + " -c '{}'".format(cmd)
elif param == 'vip':
if 'vip' in cached_data:
cache_address = cached_data[param]
data_address = data[param].data
# add vip
for d_address in data_address:
if d_address in cache_address:
continue
elif d_address != "":
d_addr = d_address.split('/')
try:
ip_address = ipaddress.ip_interface(d_addr[0])
except ValueError as err:
syslog.syslog(syslog.LOG_ERR, '[bgp vrrpd] IP address is not valid:{}'.format(err))
if ip_address.version == 4:
command = command + " -c '{} ip {}'".format(cmd, d_addr[0])
# del vip
for c_address in cache_address:
if c_address in data_address:
continue
elif c_address != "":
c_addr = c_address.split('/')
try:
ip_address = ipaddress.ip_interface(c_addr[0])
except ValueError as err:
syslog.syslog(syslog.LOG_ERR, '[bgp vrrpd] IP address is not valid:{}'.format(err))
if ip_address.version == 4:
command = command + " -c 'no {} ip {}'".format(cmd, c_addr[0])
else:
# first time to config
data_address = data[param].data
for d_address in data_address:
d_addr = d_address.split('/')
try:
ip_address = ipaddress.ip_interface(d_addr[0])
except ValueError as err:
syslog.syslog(syslog.LOG_ERR, '[bgp vrrpd] IP address is not valid:{}'.format(err))
if ip_address.version == 4:
command = command + " -c '{} ip {}'".format(cmd, d_addr[0])
elif param == 'priority':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
command = command + " -c '{} priority {}'".format(cmd, data[param].data)
elif param == 'adv_interval':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
command = command + " -c '{} advertisement-interval {}'".format(cmd, data[param].data)
elif param == 'version':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
command = command + " -c '{} version {}'".format(cmd, data[param].data)
elif param == 'admin_status':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
if data[param].data == 'down':
command = command + " -c '{} shutdown'".format(cmd)
elif data[param].data == 'up' or data[param].data == '':
command = command + " -c 'no {} shutdown'".format(cmd)
elif param == 'preempt':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
if data[param].data == 'enabled':
command = command + " -c '{} preempt'".format(cmd)
elif data[param].data == 'disabled':
command = command + " -c 'no {} preempt'".format(cmd)
data[param].status = CachedDataWithOp.STAT_SUCC
self.__update_cache_data(table_key, data)
self.__run_command(table, command)

def vrrp6_handler(self, table, key, data):
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd](vrrp6) value for {} changed to {}'.format(key, data))
#get frr vrrp6 session key
key_params = key.split('|')
intf_cmd = 'interface {}'.format(key_params[0])
cmd = 'vrrp6 {}'.format(key_params[1])
table_key = ExtConfigDBConnector.get_table_key(table, key)
comb_attr_list = ['vip']
if not data:
#VRRP instance is deleted
command = "vtysh -c 'configure terminal' -c '{}' -c 'no {}'".format(intf_cmd, cmd)
self.__run_command(table, command)
#del cache data
del(self.table_data_cache[table_key])
else:
#create/update case
command = "vtysh -c 'configure terminal' -c '{}'".format(intf_cmd)
self.__add_op_to_data(table_key, data, comb_attr_list)
cached_data = self.table_data_cache.setdefault(table_key, {})
for param in data:
if param == 'vid':
if param in cached_data and data[param].data == cached_data[param]:
continue
elif 'vip' not in data:
command = command + " -c '{}'".format(cmd)
elif param == 'vip':
if 'vip' in cached_data:
cache_address = cached_data[param]
data_address = data[param].data
for d_address in data_address:
if d_address in cache_address:
continue
elif d_address != "":
d_addr = d_address.split('/')
try:
ip_address = ipaddress.ip_interface(d_addr[0])
except ValueError as err:
syslog.syslog(syslog.LOG_ERR, '[bgp vrrpd] IPv6 address is not valid:{}'.format(err))
if ip_address.version == 6:
command = command + " -c '{} ipv6 {}'".format(cmd, d_addr[0])

for c_address in cache_address:
if c_address in data_address:
continue
elif c_address != "":
c_addr = c_address.split('/')
try:
ip_address = ipaddress.ip_interface(c_addr[0])
except ValueError as err:
syslog.syslog(syslog.LOG_ERR, '[bgp vrrpd] IPv6 address is not valid:{}'.format(err))
if ip_address.version == 6:
command = command + " -c 'no {} ipv6 {}'".format(cmd, c_addr[0])
else:
# first time to config
data_address = data[param].data
for d_address in data_address:
d_addr = d_address.split('/')
try:
ip_address = ipaddress.ip_interface(d_addr[0])
except ValueError as err:
syslog.syslog(syslog.LOG_ERR, '[bgp vrrpd] IPv6 address is not valid:{}'.format(err))
if ip_address.version == 6:
command = command + " -c '{} ipv6 {}'".format(cmd, d_addr[0])
elif param == 'priority':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
command = command + " -c '{} priority {}'".format(cmd, data[param].data)
elif param == 'adv_interval':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
command = command + " -c '{} advertisement-interval {}'".format(cmd, data[param].data)
elif param == 'version':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
command = command + " -c '{} version {}'".format(cmd, data[param].data)
elif param == 'admin_status':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
if data[param].data == 'down':
command = command + " -c '{} shutdown'".format(cmd)
elif data[param].data == 'up' or data[param].data == '':
command = command + " -c 'no {} shutdown'".format(cmd)
elif param == 'preempt':
if param in cached_data and data[param].data == cached_data[param]:
continue
else:
if data[param].data == 'enabled':
command = command + " -c '{} preempt'".format(cmd)
elif data[param].data == 'disabled':
command = command + " -c 'no {} preempt'".format(cmd)
data[param].status = CachedDataWithOp.STAT_SUCC
self.__update_cache_data(table_key, data)
self.__run_command(table, command)

def vrrp_track_handler(self, table, key, data):
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd](vrrp track) value for {} changed to {}'.format(key, data))
#get frr vrrp track key
key_params = key.split('|')
intf_cmd = 'interface {}'.format(key_params[0])
cmd = 'vrrp {} track-interface {}'.format(key_params[1], key_params[2])

if not data:
#VRRP track instance is deleted
command = "vtysh -c 'configure terminal' -c '{}' -c 'no {}'".format(intf_cmd, cmd)
self.__run_command(table, command)
else:
#create/update case
if 'priority_increment' in data:
command = "vtysh -c 'configure terminal' -c '{}' -c '{} priority-dec {}'".format(intf_cmd, cmd, data['priority_increment'])
self.__run_command(table, command)

def vrrp6_track_handler(self, table, key, data):
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd](vrrp6 track) value for {} changed to {}'.format(key, data))
#get frr vrrp6 track key
key_params = key.split('|')
intf_cmd = 'interface {}'.format(key_params[0])
cmd = 'vrrp6 {} track-interface {}'.format(key_params[1], key_params[2])

if not data:
#VRRP track instance is deleted
command = "vtysh -c 'configure terminal' -c '{}' -c 'no {}'".format(intf_cmd, cmd)
self.__run_command(table, command)
else:
#create/update case
if 'priority_increment' in data:
command = "vtysh -c 'configure terminal' -c '{}' -c '{} priority-dec {}'".format(intf_cmd, cmd, data['priority_increment'])
self.__run_command(table, command)

def vrf_handler(self, table, key, data):
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd](vrf) value for {} changed to {}'.format(key, data))
#get vrf key
Expand Down
Loading
Loading