diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index eb3e2d13..93ce4721 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -607,6 +607,44 @@ class BGPPathAttributeMpReachNLRI(_PathAttribute): return buf +@_PathAttribute.register_type(BGP_ATTR_TYPE_MP_UNREACH_NLRI) +class BGPPathAttributeMpUnreachNLRI(_PathAttribute): + _VALUE_PACK_STR = '!HB' # afi, safi + _ATTR_FLAGS = BGP_ATTR_FLAG_OPTIONAL + + def __init__(self, afi, safi, withdrawn_routes, + flags=0, type_=None, length=None): + super(BGPPathAttributeMpUnreachNLRI, self).__init__(flags=flags, + type_=type_, + length=length) + self.afi = afi + self.safi = safi + self.withdrawn_routes = withdrawn_routes + + @classmethod + def parse_value(cls, buf): + (afi, safi,) = struct.unpack_from(cls._VALUE_PACK_STR, buffer(buf)) + binnlri = buf[struct.calcsize(cls._VALUE_PACK_STR):] + nlri = [] + while binnlri: + n, binnlri = _BinAddrPrefix.parser(binnlri) + nlri.append(n) + return { + 'afi': afi, + 'safi': safi, + 'withdrawn_routes': nlri, + } + + def serialize_value(self): + buf = bytearray() + msg_pack_into(self._VALUE_PACK_STR, buf, 0, self.afi, self.safi) + binnlri = bytearray() + for n in self.withdrawn_routes: + binnlri += n.serialize() + buf += binnlri + return buf + + class BGPNLRI(_IPAddrPrefix): pass diff --git a/ryu/tests/unit/packet/test_bgp.py b/ryu/tests/unit/packet/test_bgp.py index 0dc7fb61..6e9f1a45 100644 --- a/ryu/tests/unit/packet/test_bgp.py +++ b/ryu/tests/unit/packet/test_bgp.py @@ -96,6 +96,8 @@ class Test_bgp(unittest.TestCase): bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN, next_hop='abcd', nlri=mp_nlri), + bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN, + withdrawn_routes=mp_nlri), bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300*'bar') ] nlri = [