From 7a5513c806b184ec70f3f4d507fc5304925a545f Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Wed, 13 Oct 2021 16:38:49 +0200 Subject: [PATCH] =?UTF-8?q?Patch=20to=20add=202=20parameters=20for=20contr?= =?UTF-8?q?olling=20specific=20fields=20in=20EVPN=20rou=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …te advertisements: tunnel_endpoint_ip: To allow for VTEP IPs other than the implicit local router ID mac_mobility: To insert an extended community with a sequence number for managing MAC Mobility Backport of https://github.com/faucetsdn/ryu/commit/5722c7c8 Story: #2009283 Task: #43619 Change-Id: I3c72752ee0894e8e1f3f9b50bbc7e8033e7efa4d --- os_ken/services/protocols/bgp/api/base.py | 2 ++ os_ken/services/protocols/bgp/api/prefix.py | 5 ++++- os_ken/services/protocols/bgp/bgpspeaker.py | 22 ++++++++++++++++++- .../bgp/core_managers/table_manager.py | 11 +++++++++- .../services/protocols/bgp/info_base/vrf.py | 16 ++++++++++++-- 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/os_ken/services/protocols/bgp/api/base.py b/os_ken/services/protocols/bgp/api/base.py index e4d6686e..e751c8ae 100644 --- a/os_ken/services/protocols/bgp/api/base.py +++ b/os_ken/services/protocols/bgp/api/base.py @@ -53,6 +53,8 @@ MPLS_LABELS = 'mpls_labels' TUNNEL_TYPE = 'tunnel_type' EVPN_VNI = 'vni' PMSI_TUNNEL_TYPE = 'pmsi_tunnel_type' +TUNNEL_ENDPOINT_IP = 'tunnel_endpoint_ip' +MAC_MOBILITY = 'mac_mobility' FLOWSPEC_FAMILY = 'flowspec_family' FLOWSPEC_RULES = 'rules' FLOWSPEC_ACTIONS = 'actions' diff --git a/os_ken/services/protocols/bgp/api/prefix.py b/os_ken/services/protocols/bgp/api/prefix.py index f374a947..0ef837c6 100644 --- a/os_ken/services/protocols/bgp/api/prefix.py +++ b/os_ken/services/protocols/bgp/api/prefix.py @@ -55,6 +55,8 @@ from os_ken.services.protocols.bgp.api.base import VPN_LABEL from os_ken.services.protocols.bgp.api.base import EVPN_VNI from os_ken.services.protocols.bgp.api.base import TUNNEL_TYPE from os_ken.services.protocols.bgp.api.base import PMSI_TUNNEL_TYPE +from os_ken.services.protocols.bgp.api.base import MAC_MOBILITY +from os_ken.services.protocols.bgp.api.base import TUNNEL_ENDPOINT_IP from os_ken.services.protocols.bgp.api.base import FLOWSPEC_FAMILY from os_ken.services.protocols.bgp.api.base import FLOWSPEC_RULES from os_ken.services.protocols.bgp.api.base import FLOWSPEC_ACTIONS @@ -360,7 +362,8 @@ def delete_local(route_dist, prefix, route_family=VRF_RF_IPV4): opt_args=[EVPN_ESI, EVPN_ETHERNET_TAG_ID, REDUNDANCY_MODE, MAC_ADDR, IP_ADDR, IP_PREFIX, GW_IP_ADDR, EVPN_VNI, TUNNEL_TYPE, - PMSI_TUNNEL_TYPE]) + PMSI_TUNNEL_TYPE, TUNNEL_ENDPOINT_IP, + MAC_MOBILITY]) def add_evpn_local(route_type, route_dist, next_hop, **kwargs): """Adds EVPN route from VRF identified by *route_dist*. """ diff --git a/os_ken/services/protocols/bgp/bgpspeaker.py b/os_ken/services/protocols/bgp/bgpspeaker.py index 2c3ad0c7..c3decf3c 100644 --- a/os_ken/services/protocols/bgp/bgpspeaker.py +++ b/os_ken/services/protocols/bgp/bgpspeaker.py @@ -689,7 +689,7 @@ class BGPSpeaker(object): ethernet_tag_id=None, mac_addr=None, ip_addr=None, ip_prefix=None, gw_ip_addr=None, vni=None, next_hop=None, tunnel_type=None, pmsi_tunnel_type=None, - redundancy_mode=None): + redundancy_mode=None, tunnel_endpoint_ip=None, mac_mobility=None): """ This method adds a new EVPN route to be advertised. ``route_type`` specifies one of the EVPN route type name. @@ -755,6 +755,15 @@ class BGPSpeaker(object): - REDUNDANCY_MODE_ALL_ACTIVE = 'all_active' - REDUNDANCY_MODE_SINGLE_ACTIVE = 'single_active' + + ``tunnel_endpoint_ip`` specifies a VTEP IP address other than the + local router ID. This attribute is advertised only if route_type is + EVPN_MULTICAST_ETAG_ROUTE, and defaults to the local router ID. + + ``mac_mobility`` specifies an optional integer sequence number to use + in a MAC Mobility extended community field. The special value '-1' can + be used to set the STATIC flag with a 0-value sequence number. + """ func_name = 'evpn_prefix.add_local' @@ -799,6 +808,10 @@ class BGPSpeaker(object): # Set tunnel type specific arguments if tunnel_type in [TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE]: kwargs[EVPN_VNI] = vni + + # Pass on mac_mobility, must be integer value + if mac_mobility is not None: + kwargs['mac_mobility'] = int(mac_mobility) elif route_type == EVPN_MULTICAST_ETAG_ROUTE: kwargs.update({ EVPN_ETHERNET_TAG_ID: ethernet_tag_id, @@ -815,6 +828,9 @@ class BGPSpeaker(object): elif pmsi_tunnel_type is not None: raise ValueError('Unsupported PMSI tunnel type: %s' % pmsi_tunnel_type) + # Set non-default tunnel endpoint IP, if provided + if tunnel_endpoint_ip is not None: + kwargs['tunnel_endpoint_ip'] = tunnel_endpoint_ip elif route_type == EVPN_ETH_SEGMENT: kwargs.update({ EVPN_ESI: esi, @@ -830,6 +846,10 @@ class BGPSpeaker(object): # Set tunnel type specific arguments if tunnel_type in [TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE]: kwargs[EVPN_VNI] = vni + + # Add mac_mobility + if mac_mobility is not None: + kwargs['mac_mobility'] = int(mac_mobility) else: raise ValueError('Unsupported EVPN route type: %s' % route_type) diff --git a/os_ken/services/protocols/bgp/core_managers/table_manager.py b/os_ken/services/protocols/bgp/core_managers/table_manager.py index 358c7e9c..5eab76e6 100644 --- a/os_ken/services/protocols/bgp/core_managers/table_manager.py +++ b/os_ken/services/protocols/bgp/core_managers/table_manager.py @@ -617,7 +617,8 @@ class TableCoreManager(object): def update_vrf_table(self, route_dist, prefix=None, next_hop=None, route_family=None, route_type=None, tunnel_type=None, is_withdraw=False, redundancy_mode=None, - pmsi_tunnel_type=None, **kwargs): + pmsi_tunnel_type=None, tunnel_endpoint_ip=None, + mac_mobility=None, **kwargs): """Update a BGP route in the VRF table identified by `route_dist` with the given `next_hop`. @@ -637,6 +638,13 @@ class TableCoreManager(object): This field is advertised only if route_type is EVPN_MULTICAST_ETAG_ROUTE. + `tunnel_endpoint_ip` specifies a tunnel endpoint IP other than the + default local router ID; only used in EVPN_MULTICAST_ETAG_ROUTE + + `mac_mobility` specifies an optional integer sequence number to insert + as a MAC Mobility extended community; special value `-1` is used for + static MACs (MAC Mobility sequence 0 with STATIC flag set) + Returns assigned VPN label. """ from os_ken.services.protocols.bgp.core import BgpCoreError @@ -708,6 +716,7 @@ class TableCoreManager(object): return vrf_table.insert_vrf_path( nlri=prefix, next_hop=next_hop, gen_lbl=gen_lbl, is_withdraw=is_withdraw, redundancy_mode=redundancy_mode, + mac_mobility=mac_mobility, vni=vni, tunnel_type=tunnel_type, pmsi_tunnel_type=pmsi_tunnel_type) diff --git a/os_ken/services/protocols/bgp/info_base/vrf.py b/os_ken/services/protocols/bgp/info_base/vrf.py index fef0f037..210db5bd 100644 --- a/os_ken/services/protocols/bgp/info_base/vrf.py +++ b/os_ken/services/protocols/bgp/info_base/vrf.py @@ -306,6 +306,17 @@ class VrfTable(Table): flags=flags, mpls_label=label_list[0])) + # Add MAC Move functionality + # see https://datatracker.ietf.org/doc/html/rfc7432#section-7.7 + mac_mobility_seq = kwargs.get('mac_mobility', None) + if mac_mobility_seq is not None: + from os_ken.lib.packet.bgp import BGPEvpnMacMobilityExtendedCommunity + is_static = (mac_mobility_seq == -1) # Magic value for static MACs + communities.append(BGPEvpnMacMobilityExtendedCommunity( + subtype=0, + flags=1 if is_static else 0, # 0x1 = sticky (static) MAC + sequence_number=mac_mobility_seq if not is_static else 0)) + pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \ BGPPathAttributeExtendedCommunities(communities=communities) if vrf_conf.multi_exit_disc: @@ -318,8 +329,9 @@ class VrfTable(Table): from os_ken.services.protocols.bgp.api.prefix import ( PMSI_TYPE_INGRESS_REP) if pmsi_tunnel_type == PMSI_TYPE_INGRESS_REP: - tunnel_id = PmsiTunnelIdIngressReplication( - tunnel_endpoint_ip=self._core_service.router_id) + # Support other VTEP IP than local router_id + vtep = kwargs.get('tunnel_endpoint_ip', self._core_service.router_id) + tunnel_id = PmsiTunnelIdIngressReplication(tunnel_endpoint_ip=vtep) else: # pmsi_tunnel_type == PMSI_TYPE_NO_TUNNEL_INFO tunnel_id = None pattrs[BGP_ATTR_TYEP_PMSI_TUNNEL_ATTRIBUTE] = \