diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index 2ff1b2bd..7e4d48ab 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -71,6 +71,10 @@ BGP_ATTR_TYPE_ATOMIC_AGGREGATE = 6 # 0 bytes BGP_ATTR_TYPE_AGGREGATOR = 7 # AS number and IPv4 address BGP_ATTR_TYPE_MP_REACH_NLRI = 14 # RFC 4760 BGP_ATTR_TYPE_MP_UNREACH_NLRI = 15 # RFC 4760 +BGP_ATTR_TYPE_AS4_PATH = 17 # RFC 4893 +BGP_ATTR_TYPE_AS4_AGGREGATOR = 18 # RFC 4893 + +AS_TRANS = 23456 # RFC 4893 def pad(bin, len_): @@ -247,12 +251,11 @@ class BGPPathAttributeOrigin(_PathAttribute): _ATTR_FLAGS = BGP_ATTR_FLAG_TRANSITIVE -@_PathAttribute.register_type(BGP_ATTR_TYPE_AS_PATH) -class BGPPathAttributeAsPath(_PathAttribute): +class _BGPPathAttributeAsPathCommon(_PathAttribute): _AS_SET = 1 _AS_SEQUENCE = 2 _SEG_HDR_PACK_STR = '!BB' - _AS_PACK_STR = '!H' + _AS_PACK_STR = None _ATTR_FLAGS = BGP_ATTR_FLAG_TRANSITIVE @classmethod @@ -296,6 +299,24 @@ class BGPPathAttributeAsPath(_PathAttribute): return buf +@_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. + # 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 + _AS_PACK_STR = '!H' + + +@_PathAttribute.register_type(BGP_ATTR_TYPE_AS4_PATH) +class BGPPathAttributeAs4Path(_BGPPathAttributeAsPathCommon): + _AS_PACK_STR = '!I' + + @_PathAttribute.register_type(BGP_ATTR_TYPE_NEXT_HOP) class BGPPathAttributeNextHop(_PathAttribute): _VALUE_PACK_STR = '!4s' @@ -337,15 +358,14 @@ class BGPPathAttributeAtomicAggregate(_PathAttribute): return '' -@_PathAttribute.register_type(BGP_ATTR_TYPE_AGGREGATOR) -class BGPPathAttributeAggregator(_PathAttribute): - _VALUE_PACK_STR = '!H4s' +class _BGPPathAttributeAggregatorCommon(_PathAttribute): + _VALUE_PACK_STR = None _ATTR_FLAGS = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANSITIVE def __init__(self, as_number, ip_addr, flags=0, type_=None, length=None): - super(BGPPathAttributeAggregator, self).__init__(flags=flags, - type_=type_, - length=length) + super(_BGPPathAttributeAggregatorCommon, self).__init__(flags=flags, + type_=type_, + length=length) self.as_number = as_number self.ip_addr = ip_addr @@ -365,6 +385,17 @@ class BGPPathAttributeAggregator(_PathAttribute): return buf +@_PathAttribute.register_type(BGP_ATTR_TYPE_AGGREGATOR) +class BGPPathAttributeAggregator(_BGPPathAttributeAggregatorCommon): + # XXX currently this implementation assumes 16 bit AS numbers. + _VALUE_PACK_STR = '!H4s' + + +@_PathAttribute.register_type(BGP_ATTR_TYPE_AS4_AGGREGATOR) +class BGPPathAttributeAs4Aggregator(_BGPPathAttributeAggregatorCommon): + _VALUE_PACK_STR = '!I4s' + + class BGPNLRI(_IPAddrPrefix): pass diff --git a/ryu/tests/unit/packet/test_bgp.py b/ryu/tests/unit/packet/test_bgp.py index 8d3469ac..6f2e076e 100644 --- a/ryu/tests/unit/packet/test_bgp.py +++ b/ryu/tests/unit/packet/test_bgp.py @@ -78,6 +78,10 @@ class Test_bgp(unittest.TestCase): bgp.BGPPathAttributeAtomicAggregate(), bgp.BGPPathAttributeAggregator(as_number=40000, ip_addr='192.0.2.99'), + bgp.BGPPathAttributeAs4Path(value=[[1000000], set([1000001, 1002]), + [1003, 1000004]]), + bgp.BGPPathAttributeAs4Aggregator(as_number=100040000, + ip_addr='192.0.2.99'), bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300*'bar') ] nlri = [