def unpack(cls, data): rd = RouteDistinguisher.unpack(data[:8]) esi = ESI.unpack(data[8:18]) etag = EthernetTag.unpack(data[18:22]) label = Labels.unpack(data[22:25]) return cls(rd, esi, etag, label, data)
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 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 [33,36]: # 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 [37, 40]: # 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 [49, 52]: # 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 unpack (cls, data): rd = RouteDistinguisher.unpack(data[:8]) esi = ESI.unpack(data[8:18]) etag = EthernetTag.unpack(data[18:22]) label = Labels.unpack(data[22:25]) return cls(rd,esi,etag,label,data)
def unpack_nlri(cls, afi, safi, bgp, action, addpath): nlri = cls(afi, safi, action) if addpath: nlri.path_info = PathInfo(bgp[:4]) bgp = bgp[4:] mask = bgp[0] bgp = bgp[1:] _, rd_size = Family.size.get((afi, safi), (0, 0)) rd_mask = rd_size * 8 if safi.has_label(): labels = [] while mask - rd_mask >= 24: label = int(unpack('!L', bytes([0]) + bgp[:3])[0]) bgp = bgp[3:] mask -= 24 # 3 bytes # The last 4 bits are the bottom of Stack # The last bit is set for the last label labels.append(label >> 4) # This is a route withdrawal if label == 0x800000 and action == IN.WITHDRAWN: break # This is a next-hop if label == 0x000000: break if label & 1: break nlri.labels = Labels(labels) if rd_size: mask -= rd_mask # the route distinguisher rd = bgp[:rd_size] bgp = bgp[rd_size:] nlri.rd = RouteDistinguisher(rd) if mask < 0: raise Notify(3, 10, 'invalid length in NLRI prefix') if not bgp and mask: raise Notify( 3, 10, 'not enough data for the mask provided to decode the NLRI') size = CIDR.size(mask) if len(bgp) < size: raise Notify( 3, 10, 'could not decode route with family %s (AFI %d) %s (SAFI %d)' % (AFI(afi), int(afi), SAFI(safi), int(safi))) network, bgp = bgp[:size], bgp[size:] nlri.cidr = CIDR(network + bytes(IP.length(afi) - size), mask) return nlri, bgp
def unpack_nlri(cls, afi, safi, bgp, action, addpath): nlri = cls(afi, safi, action) if addpath: nlri.path_info = PathInfo(bgp[:4]) bgp = bgp[4:] mask = ord(bgp[0]) bgp = bgp[1:] if cls.has_label(): labels = [] while bgp and mask >= 8: label = int(unpack('!L', chr(0) + bgp[:3])[0]) bgp = bgp[3:] mask -= 24 # 3 bytes # The last 4 bits are the bottom of Stack # The last bit is set for the last label labels.append(label >> 4) # This is a route withdrawal if label == 0x800000 and action == IN.WITHDRAWN: break # This is a next-hop if label == 0x000000: break if label & 1: break nlri.labels = Labels(labels) if cls.has_rd(): mask -= 8 * 8 # the 8 bytes of the route distinguisher rd = bgp[:8] bgp = bgp[8:] nlri.rd = RouteDistinguisher(rd) if mask < 0: raise Notify(3, 10, 'invalid length in NLRI prefix') if not bgp and mask: raise Notify( 3, 10, 'not enough data for the mask provided to decode the NLRI') size = CIDR.size(mask) if len(bgp) < size: raise Notify( 3, 10, 'could not decode route with AFI %d sand SAFI %d' % (afi, safi)) network, bgp = bgp[:size], bgp[size:] padding = '\0' * (IP.length(afi) - size) nlri.cidr = CIDR(network + padding, mask) return nlri, bgp
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 = 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 = data[end] iplen = length / 8 if datalen in [33, 36]: # 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 [37, 40]: # 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 [49, 52]: # 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) payload = data[end + 1:end + 1 + iplenUnpack] if payload: ip = IP.unpack(data[end + 1:end + 1 + iplenUnpack]) else: ip = None label = Labels.unpack(data[end + 1 + iplenUnpack:end + 1 + iplenUnpack + 3]) return cls(rd, esi, etag, mac, maclength, label, ip, data)
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 label(tokeniser): labels = [] value = tokeniser() if value == '[': while True: value = tokeniser() if value == ']': break labels.append(int(value)) else: labels.append(int(value)) return Labels(labels)
def label (tokeniser): labels = [] value = tokeniser() try: if value == '[': while True: value = tokeniser() if value == ']': break labels.append(int(value)) else: labels.append(int(value)) except ValueError: raise ValueError('invalid label %s' % value) return Labels(labels)
def label(self, scope, name, command, tokens): labels = [] label = tokens.pop(0) try: if label == '[': while True: try: label = tokens.pop(0) except IndexError: return self.error.set(self.syntax) if label == ']': break labels.append(int(label)) else: labels.append(int(label)) except ValueError: return self.error.set(self.syntax) nlri = scope[-1]['announce'][-1].nlri if not nlri.safi.has_label(): nlri.safi = SAFI(SAFI.nlri_mpls) nlri.labels = Labels(labels) return True