From 807185470e3ae23297d2cc5ac6438b4bccdcd451 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 30 Mar 2018 11:33:56 +0900 Subject: mrtlib: Support RFC8050 Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/mrtlib.py | 130 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 116 insertions(+), 14 deletions(-) diff --git a/ryu/lib/mrtlib.py b/ryu/lib/mrtlib.py index c8f86fc9..a89ccfcc 100644 --- a/ryu/lib/mrtlib.py +++ b/ryu/lib/mrtlib.py @@ -431,6 +431,11 @@ class TableDump2MrtRecord(MrtCommonRecord): SUBTYPE_RIB_IPV6_UNICAST = 4 SUBTYPE_RIB_IPV6_MULTICAST = 5 SUBTYPE_RIB_GENERIC = 6 + SUBTYPE_RIB_IPV4_UNICAST_ADDPATH = 8 + SUBTYPE_RIB_IPV4_MULTICAST_ADDPATH = 9 + SUBTYPE_RIB_IPV6_UNICAST_ADDPATH = 10 + SUBTYPE_RIB_IPV6_MULTICAST_ADDPATH = 11 + SUBTYPE_RIB_GENERIC_ADDPATH = 12 @TableDump2MrtMessage.register_type( @@ -595,7 +600,8 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage): RIB subtypes. The AFI/SAFI-specific RIB subtypes consist of the RIB_IPV4_UNICAST, - RIB_IPV4_MULTICAST, RIB_IPV6_UNICAST, and RIB_IPV6_MULTICAST subtypes. + RIB_IPV4_MULTICAST, RIB_IPV6_UNICAST, RIB_IPV6_MULTICAST and their + additional-path version subtypes. """ # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -614,6 +620,9 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage): # Parser class to parse the Prefix field _PREFIX_CLS = None # should be defined in subclass + # Is additional-path version? + _IS_ADDPATH = False + def __init__(self, seq_num, prefix, rib_entries, entry_count=None): self.seq_num = seq_num assert isinstance(prefix, self._PREFIX_CLS) @@ -631,7 +640,7 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage): rest = buf[2:] rib_entries = [] for i in range(entry_count): - r, rest = MrtRibEntry.parse(rest) + r, rest = MrtRibEntry.parse(rest, is_addpath=cls._IS_ADDPATH) rib_entries.insert(i, r) return entry_count, rib_entries, rest @@ -709,11 +718,62 @@ class TableDump2RibIPv6MulticastMrtMessage( _PREFIX_CLS = bgp.IP6AddrPrefix +@TableDump2MrtMessage.register_type( + TableDump2MrtRecord.SUBTYPE_RIB_IPV4_UNICAST_ADDPATH) +class TableDump2RibIPv4UnicastAddPathMrtMessage( + TableDump2AfiSafiSpecificRibMrtMessage): + """ + MRT Message for the TABLE_DUMP_V2 Type and the + SUBTYPE_RIB_IPV4_UNICAST_ADDPATH subtype. + """ + _PREFIX_CLS = bgp.IPAddrPrefix + _IS_ADDPATH = True + + +@TableDump2MrtMessage.register_type( + TableDump2MrtRecord.SUBTYPE_RIB_IPV4_MULTICAST_ADDPATH) +class TableDump2RibIPv4MulticastAddPathMrtMessage( + TableDump2AfiSafiSpecificRibMrtMessage): + """ + MRT Message for the TABLE_DUMP_V2 Type and the + SUBTYPE_RIB_IPV4_MULTICAST_ADDPATH subtype. + """ + _PREFIX_CLS = bgp.IPAddrPrefix + _IS_ADDPATH = True + + +@TableDump2MrtMessage.register_type( + TableDump2MrtRecord.SUBTYPE_RIB_IPV6_UNICAST_ADDPATH) +class TableDump2RibIPv6UnicastAddPathMrtMessage( + TableDump2AfiSafiSpecificRibMrtMessage): + """ + MRT Message for the TABLE_DUMP_V2 Type and the + SUBTYPE_RIB_IPV6_UNICAST_ADDPATH subtype. + """ + _PREFIX_CLS = bgp.IP6AddrPrefix + _IS_ADDPATH = True + + +@TableDump2MrtMessage.register_type( + TableDump2MrtRecord.SUBTYPE_RIB_IPV6_MULTICAST_ADDPATH) +class TableDump2RibIPv6MulticastAddPathMrtMessage( + TableDump2AfiSafiSpecificRibMrtMessage): + """ + MRT Message for the TABLE_DUMP_V2 Type and the + SUBTYPE_RIB_IPV6_MULTICAST_ADDPATH subtype. + """ + _PREFIX_CLS = bgp.IP6AddrPrefix + _IS_ADDPATH = True + + @TableDump2MrtMessage.register_type( TableDump2MrtRecord.SUBTYPE_RIB_GENERIC) class TableDump2RibGenericMrtMessage(TableDump2MrtMessage): """ - MRT Message for the TABLE_DUMP_V2 Type and the RIB_GENERIC subtype. + MRT Message for the TABLE_DUMP_V2 Type and the generic RIB subtypes. + + The generic RIB subtypes consist of the RIB_GENERIC and + RIB_GENERIC_ADDPATH subtypes. """ # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -729,6 +789,9 @@ class TableDump2RibGenericMrtMessage(TableDump2MrtMessage): _HEADER_FMT = '!IHB' HEADER_SIZE = struct.calcsize(_HEADER_FMT) + # Is additional-path version? + _IS_ADDPATH = False + def __init__(self, seq_num, afi, safi, nlri, rib_entries, entry_count=None): self.seq_num = seq_num @@ -749,7 +812,7 @@ class TableDump2RibGenericMrtMessage(TableDump2MrtMessage): rest = buf[2:] rib_entries = [] for i in range(entry_count): - r, rest = MrtRibEntry.parse(rest) + r, rest = MrtRibEntry.parse(rest, is_addpath=cls._IS_ADDPATH) rib_entries.insert(i, r) return entry_count, rib_entries, rest @@ -784,6 +847,16 @@ class TableDump2RibGenericMrtMessage(TableDump2MrtMessage): self.afi, self.safi) + nlri_bin + rib_bin +@TableDump2MrtMessage.register_type( + TableDump2MrtRecord.SUBTYPE_RIB_GENERIC_ADDPATH) +class TableDump2RibGenericAddPathMrtMessage(TableDump2RibGenericMrtMessage): + """ + MRT Message for the TABLE_DUMP_V2 Type and the RIB_GENERIC_ADDPATH + subtype. + """ + _IS_ADDPATH = True + + class MrtRibEntry(stringify.StringifyMixin): """ MRT RIB Entry. @@ -795,15 +868,21 @@ class MrtRibEntry(stringify.StringifyMixin): # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Originated Time | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | (Path Identifier) | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Attribute Length | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | BGP Attributes... (variable) # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # peer_index, originated_time, attr_len _HEADER_FMT = '!HIH' HEADER_SIZE = struct.calcsize(_HEADER_FMT) + # peer_index, originated_time, path_id, attr_len + _HEADER_FMT_ADDPATH = '!HIIH' + HEADER_SIZE_ADDPATH = struct.calcsize(_HEADER_FMT_ADDPATH) def __init__(self, peer_index, originated_time, bgp_attributes, - attr_len=None): + attr_len=None, path_id=None): self.peer_index = peer_index self.originated_time = originated_time assert isinstance(bgp_attributes, (list, tuple)) @@ -811,20 +890,28 @@ class MrtRibEntry(stringify.StringifyMixin): assert isinstance(attr, bgp._PathAttribute) self.bgp_attributes = bgp_attributes self.attr_len = attr_len + self.path_id = path_id @classmethod - def parse(cls, buf): - (peer_index, originated_time, attr_len) = struct.unpack_from( - cls._HEADER_FMT, buf) + def parse(cls, buf, is_addpath=False): + path_id = None + if not is_addpath: + (peer_index, originated_time, + attr_len) = struct.unpack_from(cls._HEADER_FMT, buf) + _header_size = cls.HEADER_SIZE + else: + (peer_index, originated_time, path_id, + attr_len) = struct.unpack_from(cls._HEADER_FMT_ADDPATH, buf) + _header_size = cls.HEADER_SIZE_ADDPATH - bgp_attr_bin = buf[cls.HEADER_SIZE:cls.HEADER_SIZE + attr_len] + bgp_attr_bin = buf[_header_size:_header_size + attr_len] bgp_attributes = [] while bgp_attr_bin: attr, bgp_attr_bin = bgp._PathAttribute.parser(bgp_attr_bin) bgp_attributes.append(attr) return cls(peer_index, originated_time, bgp_attributes, - attr_len), buf[cls.HEADER_SIZE + attr_len:] + attr_len, path_id), buf[_header_size + attr_len:] def serialize(self): bgp_attrs_bin = bytearray() @@ -832,10 +919,17 @@ class MrtRibEntry(stringify.StringifyMixin): bgp_attrs_bin += attr.serialize() self.attr_len = len(bgp_attrs_bin) # fixup - return struct.pack(self._HEADER_FMT, - self.peer_index, - self.originated_time, - self.attr_len) + bgp_attrs_bin + if self.path_id is None: + return struct.pack(self._HEADER_FMT, + self.peer_index, + self.originated_time, + self.attr_len) + bgp_attrs_bin + else: + return struct.pack(self._HEADER_FMT_ADDPATH, + self.peer_index, + self.originated_time, + self.path_id, + self.attr_len) + bgp_attrs_bin @six.add_metaclass(abc.ABCMeta) @@ -856,6 +950,10 @@ class Bgp4MpMrtRecord(MrtCommonRecord): SUBTYPE_BGP4MP_STATE_CHANGE_AS4 = 5 SUBTYPE_BGP4MP_MESSAGE_LOCAL = 6 SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL = 7 + SUBTYPE_BGP4MP_MESSAGE_ADDPATH = 8 + SUBTYPE_BGP4MP_MESSAGE_AS4_ADDPATH = 9 + SUBTYPE_BGP4MP_MESSAGE_LOCAL_ADDPATH = 10 + SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH = 11 @MrtRecord.register_type(MrtRecord.TYPE_BGP4MP_ET) @@ -869,6 +967,10 @@ class Bgp4MpEtMrtRecord(ExtendedTimestampMrtRecord): SUBTYPE_BGP4MP_STATE_CHANGE_AS4 = 5 SUBTYPE_BGP4MP_MESSAGE_LOCAL = 6 SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL = 7 + SUBTYPE_BGP4MP_MESSAGE_ADDPATH = 8 + SUBTYPE_BGP4MP_MESSAGE_AS4_ADDPATH = 9 + SUBTYPE_BGP4MP_MESSAGE_LOCAL_ADDPATH = 10 + SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH = 11 @Bgp4MpMrtMessage.register_type( -- cgit v1.2.3