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

Added route-advertise to bgp_af module #63

Merged
merged 27 commits into from Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/cliconf/sonic.py
Expand Up @@ -23,7 +23,7 @@

DOCUMENTATION = """
---
cliconf: sonic
name: sonic
short_description: Use sonic cliconf to run command on Dell OS10 platform
description:
- This sonic plugin provides low level abstraction apis for
Expand Down
3 changes: 1 addition & 2 deletions plugins/httpapi/sonic.py
Expand Up @@ -22,8 +22,7 @@

DOCUMENTATION = """
---
author: Ansible Networking Team
httpapi: sonic
name: sonic
short_description: HttpApi Plugin for devices supporting Restconf SONIC API
description:
- This HttpApi plugin provides methods to connect to Restconf SONIC API endpoints.
Expand Down
14 changes: 14 additions & 0 deletions plugins/module_utils/network/sonic/argspec/bgp_af/bgp_af.py
Expand Up @@ -50,6 +50,20 @@ def __init__(self, **kwargs):
'advertise_pip_ip': {'type': 'str'},
'advertise_pip_peer_ip': {'type': 'str'},
'advertise_svi_ip': {'type': 'bool'},
'route_advertise_list': {
'elements': 'dict',
'options': {
'advertise_afi': {
'choices': ['ipv4', 'ipv6'],
stalabi1 marked this conversation as resolved.
Show resolved Hide resolved
'required': True,
'type': 'str'
},
'route_map': {
'type': 'str'
}
},
'type': 'list'
},
'advertise_all_vni': {'type': 'bool'},
'advertise_default_gw': {'type': 'bool'},
'afi': {
Expand Down
104 changes: 102 additions & 2 deletions plugins/module_utils/network/sonic/config/bgp_af/bgp_af.py
Expand Up @@ -49,6 +49,7 @@
{'config': {'vrf_name': '', 'bgp_as': ''}},
{'afis': {'afi': '', 'safi': ''}},
{'redistribute': {'protocol': ''}},
{'route_advertise_list': {'advertise_afi': ''}}
]


Expand All @@ -69,6 +70,7 @@ class Bgp_af(ConfigBase):
network_instance_path = '/data/openconfig-network-instance:network-instances/network-instance'
protocol_bgp_path = 'protocols/protocol=BGP,bgp/bgp'
l2vpn_evpn_config_path = 'l2vpn-evpn/openconfig-bgp-evpn-ext:config'
l2vpn_evpn_route_advertise_path = 'l2vpn-evpn/openconfig-bgp-evpn-ext:route-advertise'
afi_safi_path = 'global/afi-safis/afi-safi'
table_connection_path = 'table-connections/table-connection'

Expand Down Expand Up @@ -169,7 +171,6 @@ def _state_merged(self, want, have, diff):
commands = update_states(commands, "merged")
else:
commands = []

return commands, requests

def _state_deleted(self, want, have, diff):
Expand All @@ -190,6 +191,7 @@ def _state_deleted(self, want, have, diff):
commands = want

requests = self.get_delete_bgp_af_requests(commands, have, is_delete_all)
requests.extend(self.get_delete_route_advertise_requests(commands, have, is_delete_all))

if commands and len(requests) > 0:
commands = update_states(commands, "deleted")
Expand Down Expand Up @@ -245,6 +247,30 @@ def get_modify_advertise_request(self, vrf_name, conf_afi, conf_safi, conf_addr_

return request

def get_modify_route_advertise_list_request(self, vrf_name, conf_afi, conf_safi, conf_addr_fam):
request = []
route_advertise = []
afi_safi = ('%s_%s' % (conf_afi, conf_safi)).upper()
route_advertise_list = conf_addr_fam.get('route_advertise_list', [])
if route_advertise_list:
for rt_adv in route_advertise_list:
advertise_afi = rt_adv.get('advertise_afi', None)
route_map = rt_adv.get('route_map', None)
if advertise_afi:
advertise_afi_safi = '%s_UNICAST' % advertise_afi.upper()
url = '%s=%s/%s' % (self.network_instance_path, vrf_name, self.protocol_bgp_path)
url += '/%s=%s/%s' % (self.afi_safi_path, afi_safi, self.l2vpn_evpn_route_advertise_path)
cfg = None
if route_map:
route_map_list = [route_map]
cfg = {'advertise-afi-safi': advertise_afi_safi, 'route-map': route_map_list}
else:
cfg = {'advertise-afi-safi': advertise_afi_safi}
route_advertise.append({'advertise-afi-safi': advertise_afi_safi, 'config': cfg})
pay_load = {'openconfig-bgp-evpn-ext:route-advertise': {'route-advertise-list': route_advertise}}
request = {"path": url, "method": PATCH, "data": pay_load}
return request

def get_modify_redistribute_requests(self, vrf_name, conf_afi, conf_safi, conf_redis_arr):
requests = []
url = "%s=%s/table-connections" % (self.network_instance_path, vrf_name)
Expand Down Expand Up @@ -350,7 +376,6 @@ def get_modify_single_af_request(self, vrf_name, conf_afi, conf_safi, conf_addr_
adv_req = self.get_modify_advertise_request(vrf_name, conf_afi, conf_safi, conf_addr_fam)
if adv_req:
requests.append(adv_req)

return requests

def get_modify_all_af_requests(self, conf_addr_fams, vrf_name):
Expand Down Expand Up @@ -400,8 +425,12 @@ def get_modify_requests(self, conf, match, vrf_name):

if conf_afi == "l2vpn" and conf_safi == "evpn":
adv_req = self.get_modify_advertise_request(vrf_name, conf_afi, conf_safi, conf_addr_fam)
rt_adv_req = self.get_modify_route_advertise_list_request(vrf_name, conf_afi, conf_safi, conf_addr_fam)
if adv_req:
requests.append(adv_req)
if rt_adv_req:
requests.append(rt_adv_req)

elif conf_afi in ["ipv4", "ipv6"] and conf_safi == "unicast":
conf_redis_arr = conf_addr_fam.get('redistribute', [])
conf_max_path = conf_addr_fam.get('max_path', None)
Expand Down Expand Up @@ -478,6 +507,77 @@ def get_delete_advertise_attribute_request(self, vrf_name, conf_afi, conf_safi,

return({"path": url, "method": DELETE})

def get_delete_route_advertise_request(self, vrf_name, conf_afi, conf_safi):
afi_safi = ('%s_%s' % (conf_afi, conf_safi)).upper()
url = '%s=%s/%s' % (self.network_instance_path, vrf_name, self.protocol_bgp_path)
url += '/%s=%s/%s' % (self.afi_safi_path, afi_safi, self.l2vpn_evpn_route_advertise_path)

return({'path': url, 'method': DELETE})

def get_delete_route_advertise_list_request(self, vrf_name, conf_afi, conf_safi, advertise_afi):
afi_safi = ('%s_%s' % (conf_afi, conf_safi)).upper()
advertise_afi_safi = '%s_UNICAST' % advertise_afi.upper()
url = '%s=%s/%s' % (self.network_instance_path, vrf_name, self.protocol_bgp_path)
url += '/%s=%s/%s/route-advertise-list=%s' % (self.afi_safi_path, afi_safi, self.l2vpn_evpn_route_advertise_path, advertise_afi_safi)

return({'path': url, 'method': DELETE})

def get_delete_route_advertise_route_map_request(self, vrf_name, conf_afi, conf_safi, advertise_afi, route_map):
afi_safi = ('%s_%s' % (conf_afi, conf_safi)).upper()
advertise_afi_safi = '%s_UNICAST' % advertise_afi.upper()
url = '%s=%s/%s' % (self.network_instance_path, vrf_name, self.protocol_bgp_path)
url += '/%s=%s/%s/route-advertise-list=%s' % (self.afi_safi_path, afi_safi, self.l2vpn_evpn_route_advertise_path, advertise_afi_safi)
url += '/config/route-map=%s' % route_map

return({'path': url, 'method': DELETE})

def get_delete_route_advertise_requests(self, commands, have, is_delete_all):
requests = []
if not is_delete_all:
for cmd in commands:
vrf_name = cmd['vrf_name']
addr_fams = cmd.get('address_family', None)
if addr_fams:
addr_fams = addr_fams.get('afis', [])
if not addr_fams:
return requests
for addr_fam in addr_fams:
afi = addr_fam.get('afi', None)
safi = addr_fam.get('safi', None)
route_advertise_list = addr_fam.get('route_advertise_list', [])
if route_advertise_list:
for rt_adv in route_advertise_list:
advertise_afi = rt_adv.get('advertise_afi', None)
route_map = rt_adv.get('route_map', None)
# Check if the commands to be deleted are configured
for conf in have:
conf_vrf_name = conf['vrf_name']
conf_addr_fams = conf.get('address_family', None)
if conf_addr_fams:
conf_addr_fams = conf_addr_fams.get('afis', [])
for conf_addr_fam in conf_addr_fams:
conf_afi = conf_addr_fam.get('afi', None)
conf_safi = conf_addr_fam.get('safi', None)
conf_route_advertise_list = conf_addr_fam.get('route_advertise_list', [])
if conf_route_advertise_list:
for conf_rt_adv in conf_route_advertise_list:
conf_advertise_afi = conf_rt_adv.get('advertise_afi', None)
conf_route_map = conf_rt_adv.get('route_map', None)
# Deletion at route-advertise level
if (not advertise_afi and vrf_name == conf_vrf_name and afi == conf_afi and safi == conf_safi):
requests.append(self.get_delete_route_advertise_request(vrf_name, afi, safi))
# Deletion at advertise-afi-safi level
if (advertise_afi and not route_map and vrf_name == conf_vrf_name and afi == conf_afi and safi ==
conf_safi and advertise_afi == conf_advertise_afi):
requests.append(self.get_delete_route_advertise_list_request(vrf_name, afi, safi, advertise_afi))
# Deletion at route-map level
if (route_map and vrf_name == conf_vrf_name and afi == conf_afi and safi == conf_safi
and advertise_afi == conf_advertise_afi and route_map == conf_route_map):
requests.append(self.get_delete_route_advertise_route_map_request(vrf_name, afi, safi,
advertise_afi, route_map))

return requests

def get_delete_dampening_request(self, vrf_name, conf_afi, conf_safi):
afi_safi = ("%s_%s" % (conf_afi, conf_safi)).upper()
url = '%s=%s/%s' % (self.network_instance_path, vrf_name, self.protocol_bgp_path)
Expand Down
25 changes: 24 additions & 1 deletion plugins/module_utils/network/sonic/facts/bgp_af/bgp_af.py
Expand Up @@ -62,7 +62,8 @@ class Bgp_afFacts(object):
'ebgp': ['use-multiple-paths', 'ebgp', 'maximum-paths'],
'ibgp': ['use-multiple-paths', 'ibgp', 'maximum-paths'],
'network': ['network-config', 'network'],
'dampening': ['route-flap-damping', 'config', 'enabled']
'dampening': ['route-flap-damping', 'config', 'enabled'],
'route_advertise_list': ['l2vpn-evpn', 'openconfig-bgp-evpn-ext:route-advertise', 'route-advertise-list'],
}

af_redis_params_map = {
Expand Down Expand Up @@ -102,6 +103,7 @@ def populate_facts(self, connection, ansible_facts, data=None):
vrf_list = [e_bgp_af['vrf_name'] for e_bgp_af in data]
self.update_max_paths(data)
self.update_network(data)
self.update_route_advertise_list(data)
bgp_redis_data = get_all_bgp_af_redistribute(self._module, vrf_list, self.af_redis_params_map)
self.update_redis_data(data, bgp_redis_data)
self.update_afis(data)
Expand Down Expand Up @@ -218,6 +220,27 @@ def update_afis(self, data):
if 'address_family' in conf:
conf['address_family'] = {'afis': conf['address_family']}

def update_route_advertise_list(self, data):
for conf in data:
afs = conf.get('address_family', [])
if afs:
for af in afs:
rt_adv_lst = []
route_advertise_list = af.get('route_advertise_list', None)
if route_advertise_list:
for rt in route_advertise_list:
rt_adv_dict = {}
advertise_afi = rt['advertise-afi-safi'].split(':')[1].split('_')[0].lower()
route_map_config = rt['config']
route_map = route_map_config.get('route-map', None)
if advertise_afi:
rt_adv_dict['advertise_afi'] = advertise_afi
if route_map:
rt_adv_dict['route_map'] = route_map[0]
if rt_adv_dict and rt_adv_dict not in rt_adv_lst:
rt_adv_lst.append(rt_adv_dict)
af['route_advertise_list'] = rt_adv_lst

def normalize_af_redis_params(self, af):
norm_af = list()
for e_af in af:
Expand Down
26 changes: 26 additions & 0 deletions plugins/modules/sonic_bgp_af.py
Expand Up @@ -133,6 +133,24 @@
description:
- Enables advertise SVI MACIP routes
type: bool
route_advertise_list:
description:
- List of advertise routes
type: list
elements: dict
suboptions:
advertise_afi:
required: True
type: str
choices:
- ipv4
- ipv6
description:
- Specifies the address family
route_map:
type: str
description:
- Specifies the route-map reference
advertise_default_gw:
description:
- Specifies the advertise default gateway flag.
Expand Down Expand Up @@ -189,6 +207,7 @@
# !
# address-family l2vpn evpn
# advertise-svi-ip
# advertise ipv6 unicast route-map aa
# advertise-pip ip 1.1.1.1 peer-ip 2.2.2.2
#!
#
Expand All @@ -206,6 +225,9 @@
advertise_svi_ip: True
advertise_all_vni: False
advertise_default_gw: False
route_advertise_list:
- advertise_afi: ipv6
route_map: aa
- afi: ipv4
safi: unicast
- afi: ipv6
Expand Down Expand Up @@ -295,6 +317,9 @@
advertise_svi_ip: True
advertise_all_vni: False
advertise_default_gw: False
route_advertise_list:
- advertise_afi: ipv4
route_map: bb
- afi: ipv4
safi: unicast
network:
Expand Down Expand Up @@ -340,6 +365,7 @@
# !
# address-family l2vpn evpn
# advertise-svi-ip
# advertise ipv4 unicast route-map bb
# advertise-pip ip 3.3.3.3 peer-ip 4.4.4.4
#
"""
Expand Down
26 changes: 26 additions & 0 deletions tests/regression/roles/sonic_bgp_af/defaults/main.yml
Expand Up @@ -93,6 +93,9 @@ tests:
advertise_pip_peer_ip: "2.2.2.2"
advertise_svi_ip: True
advertise_all_vni: True
route_advertise_list:
- advertise_afi: ipv4
route_map: rmap_reg1
- bgp_as: "{{bgp_as_2}}"
vrf_name: "{{vrf_1}}"
address_family:
Expand Down Expand Up @@ -129,6 +132,9 @@ tests:
route_map: rmap_reg2
- afi: l2vpn
safi: evpn
route_advertise_list:
- advertise_afi: ipv4
route_map: rmap_reg1
- name: test_case_03
description: Update2 created BGP AF properties
state: merged
Expand Down Expand Up @@ -174,6 +180,9 @@ tests:
advertise_pip_peer_ip: "4.4.4.4"
advertise_svi_ip: False
advertise_all_vni: False
route_advertise_list:
- advertise_afi: ipv6
route_map: rmap_reg2
- bgp_as: "{{bgp_as_2}}"
vrf_name: "{{vrf_1}}"
address_family:
Expand Down Expand Up @@ -210,6 +219,9 @@ tests:
route_map: rmap_reg2
- afi: l2vpn
safi: evpn
route_advertise_list:
- advertise_afi: ipv6
route_map: rmap_reg2
- name: test_case_04
description: Delete BGP AF properties
state: deleted
Expand Down Expand Up @@ -245,6 +257,9 @@ tests:
advertise_pip_ip: "3.3.3.3"
advertise_pip_peer_ip: "4.4.4.4"
advertise_svi_ip: False
route_advertise_list:
- advertise_afi: ipv4
route_map: rmap_reg1
- bgp_as: "{{bgp_as_2}}"
vrf_name: "{{vrf_1}}"
address_family:
Expand All @@ -270,6 +285,10 @@ tests:
- metric: "43"
protocol: connected
route_map: rmap_reg3
- afi: l2vpn
safi: evpn
route_advertise_list:
- advertise_afi: ipv4
- name: test_case_05
description: Delete1 BGP AF properties
state: deleted
Expand All @@ -284,6 +303,13 @@ tests:
- afi: ipv6
safi: unicast
redistribute:
- bgp_as: "{{bgp_as_2}}"
vrf_name: "{{vrf_1}}"
address_family:
afis:
- afi: l2vpn
safi: evpn
route_advertise_list:
- name: test_case_06
description: Delete2 BGP AF properties
state: deleted
Expand Down