1# encoding: utf-8 2""" 3sradjlan.py 4 5Created by Evelio Vila 6Copyright (c) 2014-2017 Exa Networks. All rights reserved. 7""" 8 9import json 10from struct import unpack 11from exabgp.vendoring import six 12from exabgp.util import hexstring 13 14from exabgp.vendoring.bitstring import BitArray 15from exabgp.protocol.iso import ISO 16from exabgp.bgp.message.update.attribute.bgpls.linkstate import LINKSTATE, LsGenericFlags 17from exabgp.bgp.message.notification import Notify 18 19# 0 1 2 3 20# 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 21# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 22# | Type | Length | 23# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24# | Flags | Weight | Reserved | 25# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 26# 27# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 28# | OSPF Neighbor ID / IS-IS System-ID | 29# + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 30# | | 31# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 32# 33# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 34# | SID/Label/Index (variable) | 35# +---------------------------------------------------------------+ 36# draft-gredler-idr-bgp-ls-segment-routing-ext-03 37 38 39@LINKSTATE.register() 40class SrAdjacencyLan(object): 41 TLV = 1100 42 43 def __init__(self, flags, sids, weight, undecoded=[]): 44 self.flags = flags 45 self.sids = sids 46 self.weight = weight 47 self.undecoded = undecoded 48 49 def __repr__(self): 50 return "sr_adj_lan_flags: %s, sids: %s, undecoded_sid: %s" % (self.flags, self.sids, self.undecoded) 51 52 @classmethod 53 def unpack(cls, data, length): 54 # We only support IS-IS flags for now. 55 flags = LsGenericFlags.unpack(data[0:1], LsGenericFlags.ISIS_SR_ADJ_FLAGS) 56 # Parse adj weight 57 weight = six.indexbytes(data, 1) 58 # Move pointer 4 bytes: Flags(1) + Weight(1) + Reserved(2) 59 system_id = ISO.unpack_sysid(data[4:10]) 60 data = data[10:] 61 # SID/Index/Label: according to the V and L flags, it contains 62 # either: 63 # * A 3 octet local label where the 20 rightmost bits are used for 64 # encoding the label value. In this case the V and L flags MUST 65 # be set. 66 # 67 # * A 4 octet index defining the offset in the SID/Label space 68 # advertised by this router using the encodings defined in 69 # Section 3.1. In this case V and L flags MUST be unset. 70 sids = [] 71 raw = [] 72 while data: 73 # Range Size: 3 octet value indicating the number of labels in 74 # the range. 75 if int(flags.flags['V']) and int(flags.flags['L']): 76 b = BitArray(bytes=data[:3]) 77 sid = b.unpack('uintbe:24')[0] 78 data = data[3:] 79 sids.append(sid) 80 elif (not flags.flags['V']) and (not flags.flags['L']): 81 sid = unpack('!I', data[:4])[0] 82 data = data[4:] 83 sids.append(sid) 84 else: 85 raw.append(hexstring(data)) 86 break 87 88 return cls(flags=flags, sids=sids, weight=weight, undecoded=raw) 89 90 def json(self, compact=None): 91 return ', '.join( 92 [ 93 '"sr-adj-lan-flags": {}'.format(self.flags.json()), 94 '"sids": {}'.format(json.dumps(self.sids)), 95 '"undecoded-sids": {}'.format(json.dumps(self.undecoded)), 96 '"sr-adj-lan-weight": {}'.format(json.dumps(self.weight)), 97 ] 98 ) 99