def test100_EVPNMACHashEqual(self): ''' Two indistinct EVPN NLRI should hash to the same value, and be equal ''' nlri1 = EVPNMAC( RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1"), ) nlri2 = EVPNMAC( RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1"), ) self.assertEqual(hash(nlri1), hash(nlri2)) self.assertEqual(nlri1, nlri2)
def test3_IPVPNHashEqual(self): ''' Two VPN NLRI distinct only by their *action* should hash to the same value, and be equal ''' packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32") nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), IP.pton("45.45.45.45"), OUT.ANNOUNCE) nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), IP.pton("45.45.45.45"), OUT.WITHDRAW) self.assertEqual(hash(nlri1), hash(nlri2)) self.assertTrue(nlri1.eq(nlri2)) self.assertEqual(nlri1, nlri2)
def unpack (cls, exdata): data = exdata # Get the data length to understand if addresses are IPv4 or IPv6 datalen = len(data) rd = RouteDistinguisher.unpack(data[:8]) data = data[8:] esi = ESI.unpack(data[:10]) data = data[10:] etag = EthernetTag.unpack(data[:4]) data = data[4:] iplen = ord(data[0]) data = data[1:] if datalen == (26 + 8): # Using IPv4 addresses ip = IP.unpack(data[:4]) data = data[4:] gwip = IP.unpack(data[:4]) data = data[4:] elif datalen == (26 + 32): # Using IPv6 addresses ip = IP.unpack(data[:16]) data = data[16:] gwip = IP.unpack(data[:16]) data = data[16:] else: raise Notify(3,5,"Data field length is given as %d, but EVPN route currently support only IPv4 or IPv6(34 or 58)" % iplen) label = Labels.unpack(data[:3]) return cls(rd,esi,etag,label,ip,iplen,gwip,exdata)
def test99_EVPNMACCreatePackUnpack(self): '''Test pack/unpack for E-VPN MAC routes''' nlri = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1")) packed = nlri.pack() unpacked,leftover = EVPN.unpack_nlri(AFI(AFI.l2vpn), SAFI(SAFI.evpn), packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC7432 self.assertTrue(isinstance(unpacked, EVPNMAC)) self.assertEqual("42.42.42.42:5", unpacked.rd._str()) self.assertEqual(ESI.DEFAULT, unpacked.esi.esi) self.assertEqual(EthernetTag(111), unpacked.etag) self.assertEqual(MAC("01:02:03:04:05:06"), unpacked.mac) self.assertEqual(IP.create("1.1.1.1"), unpacked.ip) self.assertEqual(1, len(unpacked.label.labels)) self.assertEqual(42, unpacked.label.labels[0])
def rd(tokeniser): try: value = tokeniser() separator = value.find(':') if separator > 0: prefix = value[:separator] suffix = int(value[separator + 1:]) # XXX: FIXME: we need much more checks here instead that the blank try/except... if '.' in prefix: data = [chr(0), chr(1)] data.extend([chr(int(_)) for _ in prefix.split('.')]) data.extend([chr(suffix >> 8), chr(suffix & 0xFF)]) distinguisher = ''.join(data) else: number = int(prefix) if number < pow(2, 16) and suffix < pow(2, 32): distinguisher = chr(0) + chr(0) + pack('!H', number) + pack( '!L', suffix) elif number < pow(2, 32) and suffix < pow(2, 16): distinguisher = chr(0) + chr(2) + pack('!L', number) + pack( '!H', suffix) else: raise ValueError('invalid route-distinguisher %s' % value) except ValueError: raise ValueError('invalid route-distinguisher %s' % value) return RouteDistinguisher(distinguisher)
def unpack (cls, data): datalen = len(data) rd = RouteDistinguisher.unpack(data[:8]) esi = ESI.unpack(data[8:18]) etag = EthernetTag.unpack(data[18:22]) maclength = ord(data[22]) if (maclength > 48 or maclength < 0): raise Notify(3,5,'invalid MAC Address length in %s' % cls.NAME) end = 23 + 6 # MAC length MUST be 6 mac = MACQUAL.unpack(data[23:end]) length = ord(data[end]) iplen = length / 8 if datalen in [36,39]: # No IP information (1 or 2 labels) iplenUnpack = 0 if iplen != 0: raise Notify(3,5,"IP length is given as %d, but current MAC route has no IP information" % iplen) elif datalen in [40, 43]: # Using IPv4 addresses (1 or 2 labels) iplenUnpack = 4 if (iplen > 32 or iplen < 0): raise Notify(3,5,"IP field length is given as %d, but current MAC route is IPv4 and valus is out of range" % iplen) elif datalen in [52, 55]: # Using IPv6 addresses (1 or 2 labels) iplenUnpack = 16 if (iplen > 128 or iplen < 0): raise Notify(3,5,"IP field length is given as %d, but current MAC route is IPv6 and valus is out of range" % iplen) else: raise Notify(3,5,"Data field length is given as %d, but does not match one of the expected lengths" % datalen) ip = IP.unpack(data[end+1:end+1+iplenUnpack]) label = Labels.unpack(data[end+1+iplenUnpack:end+1+iplenUnpack+3]) return cls(rd,esi,etag,mac,maclength,label,ip,data)
def test200_IPVPNCreatePackUnpack(self): '''Test pack/unpack for IPVPN routes''' nlri = IPVPN.new( AFI.ipv4, SAFI.mpls_vpn, IP.pton("1.2.3.0"), 24, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), ) packed = nlri.pack() unpacked, leftover = IPVPN.unpack_nlri(AFI.ipv4, SAFI.mpls_vpn, packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC4364 self.assertTrue(isinstance(unpacked, IPVPN)) self.assertEqual("1.2.3.0/24", unpacked.cidr.prefix()) self.assertEqual(1, len(unpacked.labels.labels)) self.assertEqual(42, unpacked.labels.labels[0]) self.assertEqual("42.42.42.42:5", unpacked.rd._str())
def test99_EVPNPrefixCreatePackUnpack(self): '''Test pack/unpack for E-VPN Prefix routes''' nlri = EVPNPrefix(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), Labels([42], True), IP.create("1.1.1.0"),24, IP.create("2.2.2.2"), ) packed = nlri.pack() unpacked,leftover = EVPN.unpack_nlri(AFI.l2vpn, SAFI.evpn, packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC7432 self.assertTrue(isinstance(unpacked, EVPNPrefix)) self.assertEqual("42.42.42.42:5", unpacked.rd._str()) self.assertEqual(ESI.DEFAULT, unpacked.esi.esi) self.assertEqual(EthernetTag(111), unpacked.etag) self.assertEqual(IP.create("1.1.1.0"), unpacked.ip) self.assertEqual(24, unpacked.iplen) self.assertEqual(IP.create("2.2.2.2"), unpacked.gwip) self.assertEqual(1, len(unpacked.label.labels)) self.assertEqual(42, unpacked.label.labels[0])
def test99_EVPNMACCreatePackUnpack(self): '''Test pack/unpack for E-VPN MAC routes''' nlri = EVPNMAC( RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1"), ) packed = nlri.pack() unpacked, leftover = EVPN.unpack_nlri(AFI.l2vpn, SAFI.evpn, packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC7432 self.assertTrue(isinstance(unpacked, EVPNMAC)) self.assertEqual("42.42.42.42:5", unpacked.rd._str()) self.assertEqual(ESI.DEFAULT, unpacked.esi.esi) self.assertEqual(EthernetTag(111), unpacked.etag) self.assertEqual(MAC("01:02:03:04:05:06"), unpacked.mac) self.assertEqual(IP.create("1.1.1.1"), unpacked.ip) self.assertEqual(1, len(unpacked.label.labels)) self.assertEqual(42, unpacked.label.labels[0])
def unpack (cls,afi,safi,bgp,addpath,nexthop,action): labels,rd,mask,size,prefix,left = NLRI._nlri(afi,safi,bgp,action) nlri = cls(afi,safi,prefix,mask,nexthop,action) if labels: nlri.labels = Labels(labels) if rd: nlri.rd = RouteDistinguisher(rd) return len(bgp) - len(left),nlri
def unpack(cls,data): rd = RouteDistinguisher.unpack(data[:8]) etag = EthernetTag.unpack(data[8:12]) iplen = ord(data[12]) ip = IP.unpack(data[12:12+iplen]) if iplen not in (4,16): raise Exception("IP len is %d, but EVPN route currently support only IPv4" % iplen) return cls(rd,etag,ip)
def generate_rd(rd): """only ip:num is supported atm.code from configure.file""" separator = rd.find(':') prefix = rd[:separator] suffix = int(rd[separator + 1:]) data = [chr(0), chr(1)] data.extend([chr(int(_)) for _ in prefix.split('.')]) data.extend([chr(suffix >> 8), chr(suffix & 0xFF)]) bin_rd = ''.join(data) return RouteDistinguisher(bin_rd)
def test2_IPVPNHashEqual(self): ''' Two VPN NLRI distinct only by their *nexthop* should hash to the same value, and be equal ''' packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32") nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), IP.pton("45.45.45.45"), OUT.ANNOUNCE) nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), IP.pton("77.77.77.77"), OUT.ANNOUNCE) self.assertEqual(hash(nlri1), hash(nlri2)) self.assertTrue(nlri1.eq(nlri2)) self.assertNotEqual(nlri1, nlri2)
def unpack(cls, afi, safi, bgp, addpath, nexthop, action): labels, rd, path_identifier, mask, size, prefix, left = NLRI._nlri( afi, safi, bgp, action, addpath) nlri = cls(afi, safi, prefix, mask, nexthop, action) if labels: nlri.labels = Labels(labels) if rd: nlri.rd = RouteDistinguisher(rd) if path_identifier: nlri.path_info = PathInfo(None, None, path_identifier) return len(bgp) - len(left), nlri
def unpack (cls,afi,safi,data,addpath,nexthop,action): # label is 20bits, stored using 3 bytes, 24 bits length, = unpack('!H',data[0:2]) if len(data) != length+2: raise Notify(3,10,'l2vpn vpls message length is not consistent with encoded data') rd = RouteDistinguisher(data[2:10]) ve,offset,size = unpack('!HHH',data[10:16]) base = unpack('!L','\x00'+data[16:19])[0]>>4 nlri = cls(rd,ve,base,offset,size) nlri.action = action nlri.nexthop = IP.unpack(nexthop) return len(data), nlri
def test100_EVPNMACHashEqual(self): ''' Two indistinct EVPN NLRI should hash to the same value, and be equal ''' nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1")) nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1")) self.assertEqual(hash(nlri1), hash(nlri2)) self.assertEqual(nlri1, nlri2)
def test101_EVPNHashEqual_somefieldsvary(self): ''' Two EVPN MAC NLRIs differing by their ESI or label or RD, or nexthop, but otherwise identical should hash to the same value, and be equal ''' nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1")) # Esi nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(['1' for _ in range(0, 10)]), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1")) # label nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([4444], True), IP.create("1.1.1.1")) # IP: different IPs, but same MACs: different route nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("2.2.2.2")) # with a next hop... nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1"), IP.pton("10.10.10.10")) nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(), EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True), IP.create("1.1.1.1"), IP.pton("11.11.11.11")) self.assertEqual(hash(nlri0), hash(nlri1)) self.assertEqual(hash(nlri0), hash(nlri2)) self.assertEqual(hash(nlri0), hash(nlri4)) self.assertEqual(nlri0, nlri1) self.assertEqual(nlri0, nlri2) self.assertEqual(nlri0, nlri4) self.assertEqual(nlri1, nlri2) self.assertEqual(nlri1, nlri4) self.assertEqual(nlri2, nlri4) self.assertEqual(nlri4, nlri5) self.assertNotEqual(hash(nlri0), hash(nlri3)) self.assertNotEqual(nlri0, nlri3) self.assertNotEqual(nlri1, nlri3) self.assertNotEqual(nlri2, nlri3) self.assertNotEqual(nlri3, nlri4)
def test2_MPLSVPNHashEqual(self): ''' Two VPN NLRI distinct only by their *nexthop* should hash to the same value, and be equal ''' packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32") nlri1 = MPLSVPN(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), IP.pton("45.45.45.45"), OUT.ANNOUNCE) nlri2 = MPLSVPN(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5), IP.pton("77.77.77.77"), OUT.ANNOUNCE) self.assertEqual(hash(nlri1), hash(nlri2)) self.assertEqual(nlri1, nlri2)
def unpack(cls, data): datalen = len(data) rd = RouteDistinguisher.unpack(data[:8]) esi = ESI.unpack(data[8:18]) etag = EthernetTag.unpack(data[18:22]) maclength = ord(data[22]) if (maclength > 48 or maclength < 0): raise Notify(3, 5, 'invalid MAC Address length in %s' % cls.NAME) end = 23 + 6 # MAC length MUST be 6 mac = MACQUAL.unpack(data[23:end]) length = ord(data[end]) iplen = length / 8 if datalen in [36, 39]: # No IP information (1 or 2 labels) iplenUnpack = 0 if iplen != 0: raise Notify( 3, 5, "IP length is given as %d, but current MAC route has no IP information" % iplen) elif datalen in [40, 43]: # Using IPv4 addresses (1 or 2 labels) iplenUnpack = 4 if (iplen > 32 or iplen < 0): raise Notify( 3, 5, "IP field length is given as %d, but current MAC route is IPv4 and valus is out of range" % iplen) elif datalen in [52, 55]: # Using IPv6 addresses (1 or 2 labels) iplenUnpack = 16 if (iplen > 128 or iplen < 0): raise Notify( 3, 5, "IP field length is given as %d, but current MAC route is IPv6 and valus is out of range" % iplen) else: raise Notify( 3, 5, "Data field length is given as %d, but does not match one of the expected lengths" % datalen) ip = IP.unpack(data[end + 1:end + 1 + iplenUnpack]) label = Labels.unpack(data[end + 1 + iplenUnpack:]) return cls(rd, esi, etag, mac, maclength, label, ip, data)
def test0_IPVPNHashEqual(self): ''' Two indistinct VPN NLRIs should hash to the same value, and be equal ''' rd = RouteDistinguisher.fromElements("42.42.42.42", 5) packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32") nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), rd, IP.pton("45.45.45.45"), OUT.ANNOUNCE) nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix, mask, Labels([42], True), rd, IP.pton("45.45.45.45"), OUT.ANNOUNCE) self.assertEqual(hash(nlri1), hash(nlri2)) self.assertEqual(nlri1, nlri2)
def test99_EVPNMulticastCreatePackUnpack(self): '''Test pack/unpack for E-VPN Multicast routes''' nlri = EVPNMulticast(RouteDistinguisher.fromElements("42.42.42.42", 5), EthernetTag(111), IP.create("1.1.1.1")) packed = nlri.pack() unpacked, leftover = EVPN.unpack_nlri(AFI.l2vpn, SAFI.evpn, packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC7432 self.assertTrue(isinstance(unpacked, EVPNMulticast)) self.assertEqual("42.42.42.42:5", unpacked.rd._str()) self.assertEqual(EthernetTag(111), unpacked.etag) self.assertEqual(IP.create("1.1.1.1"), unpacked.ip)
def unpack(cls,data): rd = RouteDistinguisher.unpack(data[:8]) esi = ESI.unpack(data[8:18]) etag = EthernetTag.unpack(data[18:22]) length = ord(data[22]) if length % 8 != 0: raise Exception('invalid MAC Address length in %s' % cls.NAME) end = 23 + length/8 mac = MAC.unpack(data[23:end]) length = ord(data[end]) if length % 8 != 0: raise Exception('invalid IP Address length in %s' % cls.NAME) iplen = length / 8 ip = IP.unpack(data[end+1:end+1+iplen]) label = Labels.unpack(data[end+1+iplen:]) return cls(rd,esi,etag,mac,label,ip,data)
def test99_EVPNMulticastCreatePackUnpack(self): '''Test pack/unpack for E-VPN Multicast routes''' nlri = EVPNMulticast(RouteDistinguisher.fromElements("42.42.42.42", 5), EthernetTag(111), IP.create("1.1.1.1")) packed = nlri.pack() unpacked,leftover = EVPN.unpack_nlri(AFI(AFI.l2vpn), SAFI(SAFI.evpn), packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC7432 self.assertTrue(isinstance(unpacked, EVPNMulticast)) self.assertEqual("42.42.42.42:5", unpacked.rd._str()) self.assertEqual(EthernetTag(111), unpacked.etag) self.assertEqual(IP.create("1.1.1.1"), unpacked.ip)
def test200_IPVPNCreatePackUnpack(self): '''Test pack/unpack for IPVPN routes''' nlri = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), IP.pton("1.2.3.0"), 24, Labels([42], True), RouteDistinguisher.fromElements("42.42.42.42", 5)) packed = nlri.pack() unpacked,leftover = IPVPN.unpack_nlri(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packed, OUT.UNSET, None) self.assertEqual(0, len(leftover)) # TODO: compare packed with a reference encoding verified # as conformant with RFC4364 self.assertTrue(isinstance(unpacked, IPVPN)) self.assertEqual("1.2.3.0/24", unpacked.cidr.prefix()) self.assertEqual(1, len(unpacked.labels.labels)) self.assertEqual(42, unpacked.labels.labels[0]) self.assertEqual("42.42.42.42:5", unpacked.rd._str())
def unpack(cls, exdata): data = exdata # Get the data length to understand if addresses are IPv4 or IPv6 datalen = len(data) rd = RouteDistinguisher.unpack(data[:8]) data = data[8:] esi = ESI.unpack(data[:10]) data = data[10:] etag = EthernetTag.unpack(data[:4]) data = data[4:] iplen = ord(data[0]) data = data[1:] if datalen == (26 + 8): # Using IPv4 addresses ip = IP.unpack(data[:4]) data = data[4:] gwip = IP.unpack(data[:4]) data = data[4:] elif datalen == (26 + 32): # Using IPv6 addresses ip = IP.unpack(data[:16]) data = data[16:] gwip = IP.unpack(data[:16]) data = data[16:] else: raise Notify( 3, 5, "Data field length is given as %d, but EVPN route currently support only IPv4 or IPv6(34 or 58)" % iplen) label = Labels.unpack(data[:3]) return cls(rd, esi, etag, label, ip, iplen, gwip, exdata)
def test101_EVPNHashEqual_somefieldsvary(self): ''' Two EVPN MAC NLRIs differing by their ESI or label or RD, or nexthop, but otherwise identical should hash to the same value, and be equal ''' nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1")) # Esi nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(1), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1")) # label nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([4444], True), IP.create("1.1.1.1")) # IP: different IPs, but same MACs: different route nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("2.2.2.2")) # with a next hop... nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1"), IP.pton("10.10.10.10")) nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5), ESI(0), EthernetTag(111), MAC("01:02:03:04:05:06"), 6*8, Labels([42], True), IP.create("1.1.1.1"), IP.pton("11.11.11.11")) self.assertEqual(hash(nlri0), hash(nlri1)) self.assertEqual(hash(nlri0), hash(nlri2)) self.assertEqual(hash(nlri0), hash(nlri4)) self.assertEqual(nlri0, nlri1) self.assertEqual(nlri0, nlri2) self.assertEqual(nlri0, nlri4) self.assertEqual(nlri1, nlri2) self.assertEqual(nlri1, nlri4) self.assertEqual(nlri2, nlri4) self.assertEqual(nlri4, nlri5) self.assertNotEqual(hash(nlri0), hash(nlri3)) self.assertNotEqual(nlri0, nlri3) self.assertNotEqual(nlri1, nlri3) self.assertNotEqual(nlri2, nlri3) self.assertNotEqual(nlri3, nlri4)
def unpack(cls, afi, safi, bgp, has_multiple_path, nexthop, action): total = len(bgp) length, bgp = ord(bgp[0]), bgp[1:] if length & 0xF0 == 0xF0: # bigger than 240 extra, bgp = ord(bgp[0]), bgp[1:] length = ((length & 0x0F) << 16) + extra if length > len(bgp): raise Notify(3, 10, 'invalid length at the start of the the flow') bgp = bgp[:length] nlri = Flow(afi, safi, nexthop) nlri.action = action if safi == SAFI.flow_vpn: nlri.rd = RouteDistinguisher(bgp[:8]) bgp = bgp[8:] seen = [] while bgp: what, bgp = ord(bgp[0]), bgp[1:] if what not in decode.get(afi, {}): raise Notify( 3, 10, 'unknown flowspec component received for address family %d' % what) seen.append(what) if sorted(seen) != seen: raise Notify( 3, 10, 'components are not sent in the right order %s' % seen) decoded = decode[afi][what] klass = factory[afi][what] if decoded == 'prefix': if afi == AFI.ipv4: _, rd, _, mask, size, prefix, left = NLRI._nlri( afi, safi, bgp, action, False) adding = klass(prefix, mask) if not nlri.add(adding): raise Notify( 3, 10, 'components are incompatible (two sources, two destinations, mix ipv4/ipv6) %s' % seen) # logger.parser(LazyFormat("added flow %s (%s) payload " % (klass.NAME,adding),bgp[:-len(left)])) bgp = left else: byte, bgp = bgp[1], bgp[0] + bgp[2:] offset = ord(byte) _, rd, _, mask, size, prefix, left = NLRI._nlri( afi, safi, bgp, action, False) adding = klass(prefix, mask, offset) if not nlri.add(adding): raise Notify( 3, 10, 'components are incompatible (two sources, two destinations, mix ipv4/ipv6) %s' % seen) # logger.parser(LazyFormat("added flow %s (%s) payload " % (klass.NAME,adding),bgp[:-len(left)])) bgp = left else: end = False while not end: byte, bgp = ord(bgp[0]), bgp[1:] end = CommonOperator.eol(byte) operator = CommonOperator.operator(byte) length = CommonOperator.length(byte) value, bgp = bgp[:length], bgp[length:] adding = klass.decoder(value) nlri.add(klass(operator, adding)) # logger.parser(LazyFormat("added flow %s (%s) operator %d len %d payload " % (klass.NAME,adding,byte,length),value)) return total - len(bgp), nlri