diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2014-08-05 18:41:40 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2014-08-06 08:46:19 +0800 |
commit | 5fb5b6c57d8783c974fff469249a8013aa49c653 (patch) | |
tree | 7fa5a8ab559dabf7c1fa06d561af9a0b4c96c93f | |
parent | 94d5d865f07467bfe918191cd9c3d9481343cd94 (diff) |
packet/bgp: add 32bit AS number support to BGPPathAttributeAsPath
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/lib/packet/bgp.py | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index b91ece7e..5526ab60 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -1325,6 +1325,15 @@ class _BGPPathAttributeAsPathCommon(_PathAttribute): _AS_PACK_STR = None _ATTR_FLAGS = BGP_ATTR_FLAG_TRANSITIVE + def __init__(self, value, as_pack_str=None, flags=0, type_=None, + length=None): + super(_BGPPathAttributeAsPathCommon, self).__init__(value=value, + flags=flags, + type_=type_, + length=length) + if as_pack_str: + self._AS_PACK_STR = as_pack_str + @property def path_seg_list(self): return copy.deepcopy(self.value) @@ -1361,17 +1370,44 @@ class _BGPPathAttributeAsPathCommon(_PathAttribute): return False @classmethod + def _is_valid_16bit_as_path(cls, buf): + + two_byte_as_size = struct.calcsize('!H') + + while buf: + (type_, num_as) = struct.unpack_from(cls._SEG_HDR_PACK_STR, + buffer(buf)) + + if type_ is not cls._AS_SET and type_ is not cls._AS_SEQUENCE: + return False + + buf = buf[struct.calcsize(cls._SEG_HDR_PACK_STR):] + + if len(buf) < num_as * two_byte_as_size: + return False + + buf = buf[num_as * two_byte_as_size:] + + return True + + @classmethod def parse_value(cls, buf): result = [] + + if cls._is_valid_16bit_as_path(buf): + as_pack_str = '!H' + else: + as_pack_str = '!I' + while buf: (type_, num_as) = struct.unpack_from(cls._SEG_HDR_PACK_STR, buffer(buf)) buf = buf[struct.calcsize(cls._SEG_HDR_PACK_STR):] l = [] for i in xrange(0, num_as): - (as_number,) = struct.unpack_from(cls._AS_PACK_STR, + (as_number,) = struct.unpack_from(as_pack_str, buffer(buf)) - buf = buf[struct.calcsize(cls._AS_PACK_STR):] + buf = buf[struct.calcsize(as_pack_str):] l.append(as_number) if type_ == cls._AS_SET: result.append(set(l)) @@ -1380,7 +1416,8 @@ class _BGPPathAttributeAsPathCommon(_PathAttribute): else: assert(0) # protocol error return { - 'value': result + 'value': result, + 'as_pack_str': as_pack_str, } def serialize_value(self): @@ -1405,14 +1442,15 @@ class _BGPPathAttributeAsPathCommon(_PathAttribute): @_PathAttribute.register_type(BGP_ATTR_TYPE_AS_PATH) class BGPPathAttributeAsPath(_BGPPathAttributeAsPathCommon): - # XXX currently this implementation assumes 16 bit AS numbers. - # depends on negotiated capability, AS numbers can be 32 bit. + # XXX depends on negotiated capability, AS numbers can be 32 bit. # while wireshark seems to attempt auto-detect, it seems that # there's no way to detect it reliably. for example, the # following byte sequence can be interpreted in two ways. # 01 02 99 88 77 66 02 01 55 44 # AS_SET num=2 9988 7766 AS_SEQUENCE num=1 5544 # AS_SET num=2 99887766 02015544 + # we first check whether AS path can be parsed in 16bit format and if + # it fails, we try to parse as 32bit _AS_PACK_STR = '!H' @@ -1420,6 +1458,10 @@ class BGPPathAttributeAsPath(_BGPPathAttributeAsPathCommon): class BGPPathAttributeAs4Path(_BGPPathAttributeAsPathCommon): _AS_PACK_STR = '!I' + @classmethod + def _is_valid_16bit_as_path(cls, buf): + return False + @_PathAttribute.register_type(BGP_ATTR_TYPE_NEXT_HOP) class BGPPathAttributeNextHop(_PathAttribute): |