BGPSpeaker: Support to advertise Tunnel Encapsulation

This patch adds support to advertise the BGP Tunnel Encapsulation
Attribute for the Ethernet VPN Routes.

Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
IWASE Yusuke 2016-09-05 09:41:35 +09:00 committed by FUJITA Tomonori
parent bd4e8a70b5
commit 40fe7ffdc5
6 changed files with 65 additions and 6 deletions

View File

@ -2795,6 +2795,26 @@ class BGPEncapsulationExtendedCommunity(_ExtendedCommunity):
super(BGPEncapsulationExtendedCommunity, self).__init__()
self.do_init(BGPEncapsulationExtendedCommunity, self, kwargs)
@classmethod
def from_str(cls, tunnel_type):
"""
Returns an instance identified with the given `tunnel_type`.
`tunnel_type` should be a str type value and corresponding to
BGP Tunnel Encapsulation Attribute Tunnel Type constants name
omitting `TUNNEL_TYPE_` prefix.
Example:
- `gre` means TUNNEL_TYPE_GRE
- `vxlan` means TUNNEL_TYPE_VXLAN
And raises AttributeError when the corresponding Tunnel Type
is not found to the given `tunnel_type`.
"""
return cls(subtype=_ExtendedCommunity.SUBTYPE_ENCAPSULATION,
tunnel_type=getattr(cls,
'TUNNEL_TYPE_' + tunnel_type.upper()))
@_ExtendedCommunity.register_type(_ExtendedCommunity.EVPN_MAC_MOBILITY)
class BGPEvpnMacMobilityExtendedCommunity(_ExtendedCommunity):

View File

@ -49,6 +49,7 @@ EVPN_ETHERNET_TAG_ID = 'ethernet_tag_id'
MAC_ADDR = 'mac_addr'
IP_ADDR = 'ip_addr'
MPLS_LABELS = 'mpls_labels'
TUNNEL_TYPE = 'tunnel_type'
# API call registry
_CALL_REGISTRY = {}

View File

@ -31,6 +31,7 @@ from ryu.services.protocols.bgp.api.base import PREFIX
from ryu.services.protocols.bgp.api.base import RegisterWithArgChecks
from ryu.services.protocols.bgp.api.base import ROUTE_DISTINGUISHER
from ryu.services.protocols.bgp.api.base import VPN_LABEL
from ryu.services.protocols.bgp.api.base import TUNNEL_TYPE
from ryu.services.protocols.bgp.base import add_bgp_error_metadata
from ryu.services.protocols.bgp.base import PREFIX_ERROR_CODE
from ryu.services.protocols.bgp.base import validate
@ -54,6 +55,20 @@ SUPPORTED_EVPN_ROUTE_TYPES = [
EVPN_MULTICAST_ETAG_ROUTE,
]
# Constants for BGP Tunnel Encapsulation Attribute
TUNNEL_TYPE_VXLAN = 'vxlan'
TUNNEL_TYPE_NVGRE = 'nvgre'
TUNNEL_TYPE_MPLS = 'mpls'
TUNNEL_TYPE_MPLS_IN_GRE = 'mpls_in_gre'
TUNNEL_TYPE_VXLAN_GRE = 'vxlan_gre'
SUPPORTED_TUNNEL_TYPES = [
TUNNEL_TYPE_VXLAN,
TUNNEL_TYPE_NVGRE,
TUNNEL_TYPE_MPLS,
TUNNEL_TYPE_MPLS_IN_GRE,
TUNNEL_TYPE_VXLAN_GRE,
]
@add_bgp_error_metadata(code=PREFIX_ERROR_CODE,
sub_code=1,
@ -122,6 +137,13 @@ def is_valid_mpls_labels(labels):
conf_value=labels)
@validate(name=TUNNEL_TYPE)
def is_valid_tunnel_type(tunnel_type):
if tunnel_type not in SUPPORTED_TUNNEL_TYPES:
raise ConfigValueError(conf_name=TUNNEL_TYPE,
conf_value=tunnel_type)
@RegisterWithArgChecks(name='prefix.add_local',
req_args=[ROUTE_DISTINGUISHER, PREFIX, NEXT_HOP],
opt_args=[VRF_RF])
@ -171,7 +193,7 @@ def delete_local(route_dist, prefix, route_family=VRF_RF_IPV4):
req_args=[EVPN_ROUTE_TYPE, ROUTE_DISTINGUISHER,
NEXT_HOP],
opt_args=[EVPN_ESI, EVPN_ETHERNET_TAG_ID, MAC_ADDR,
IP_ADDR])
IP_ADDR, TUNNEL_TYPE])
def add_evpn_local(route_type, route_dist, next_hop, **kwargs):
"""Adds EVPN route from VRF identified by *route_dist*.
"""

View File

@ -31,8 +31,10 @@ from ryu.services.protocols.bgp.api.base import MAC_ADDR
from ryu.services.protocols.bgp.api.base import NEXT_HOP
from ryu.services.protocols.bgp.api.base import ROUTE_DISTINGUISHER
from ryu.services.protocols.bgp.api.base import ROUTE_FAMILY
from ryu.services.protocols.bgp.api.base import TUNNEL_TYPE
from ryu.services.protocols.bgp.api.prefix import EVPN_MAC_IP_ADV_ROUTE
from ryu.services.protocols.bgp.api.prefix import EVPN_MULTICAST_ETAG_ROUTE
from ryu.services.protocols.bgp.api.prefix import TUNNEL_TYPE_MPLS
from ryu.services.protocols.bgp.rtconf.common import LOCAL_AS
from ryu.services.protocols.bgp.rtconf.common import ROUTER_ID
from ryu.services.protocols.bgp.rtconf.common import BGP_SERVER_PORT
@ -490,7 +492,7 @@ class BGPSpeaker(object):
def evpn_prefix_add(self, route_type, route_dist, esi=0,
ethernet_tag_id=None, mac_addr=None, ip_addr=None,
next_hop=None):
next_hop=None, tunnel_type=TUNNEL_TYPE_MPLS):
""" This method adds a new EVPN route to be advertised.
``route_type`` specifies one of the EVPN route type name. The
@ -509,6 +511,9 @@ class BGPSpeaker(object):
``ip_addr`` specifies an IPv4 or IPv6 address to advertise.
``next_hop`` specifies the next hop address for this prefix.
``tunnel_type`` specifies the data plane encapsulation type
to advertise. The default is the MPLS encapsulation type.
"""
func_name = 'evpn_prefix.add_local'
@ -521,6 +526,10 @@ class BGPSpeaker(object):
ROUTE_DISTINGUISHER: route_dist,
NEXT_HOP: next_hop}
# Set optional arguments
if tunnel_type:
kwargs[TUNNEL_TYPE] = tunnel_type
# Set route type specific arguments
if route_type == EVPN_MAC_IP_ADV_ROUTE:
kwargs.update({

View File

@ -482,7 +482,7 @@ class TableCoreManager(object):
LOG.debug('No VRF table found that imports RTs: %s', path_rts)
def update_vrf_table(self, route_dist, prefix=None, next_hop=None,
route_family=None, route_type=None,
route_family=None, route_type=None, tunnel_type=None,
is_withdraw=False, **kwargs):
"""Update a BGP route in the VRF table identified by `route_dist`
with the given `next_hop`.
@ -547,7 +547,7 @@ class TableCoreManager(object):
# withdrawal. Hence multiple withdrawals have not side effect.
return vrf_table.insert_vrf_path(
nlri=prefix, next_hop=next_hop, gen_lbl=gen_lbl,
is_withdraw=is_withdraw)
is_withdraw=is_withdraw, tunnel_type=tunnel_type)
def update_global_table(self, prefix, next_hop=None, is_withdraw=False):
"""Update a BGP route in the Global table for the given `prefix`

View File

@ -30,6 +30,7 @@ from ryu.lib.packet.bgp import BGPPathAttributeAsPath
from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities
from ryu.lib.packet.bgp import BGPTwoOctetAsSpecificExtendedCommunity
from ryu.lib.packet.bgp import BGPPathAttributeMultiExitDisc
from ryu.lib.packet.bgp import BGPEncapsulationExtendedCommunity
from ryu.lib.packet.bgp import RF_L2_EVPN
from ryu.lib.packet.bgp import EvpnMacIPAdvertisementNLRI
@ -211,7 +212,7 @@ class VrfTable(Table):
return changed_dests
def insert_vrf_path(self, nlri, next_hop=None,
gen_lbl=False, is_withdraw=False):
gen_lbl=False, is_withdraw=False, **kwargs):
assert nlri
pattrs = None
label_list = []
@ -243,6 +244,12 @@ class VrfTable(Table):
local_administrator=int(local_admin),
subtype=subtype))
# Set Tunnel Encapsulation Attribute
tunnel_type = kwargs.get('tunnel_type', None)
if tunnel_type:
communities.append(
BGPEncapsulationExtendedCommunity.from_str(tunnel_type))
pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \
BGPPathAttributeExtendedCommunities(communities=communities)
if vrf_conf.multi_exit_disc:
@ -266,7 +273,7 @@ class VrfTable(Table):
label_list.append(table_manager.get_next_vpnv4_label())
# Set MPLS labels with the generated labels
if isinstance(nlri, EvpnMacIPAdvertisementNLRI):
if gen_lbl and isinstance(nlri, EvpnMacIPAdvertisementNLRI):
nlri.mpls_labels = label_list[:2]
puid = self.VRF_PATH_CLASS.create_puid(