implement BGP-4 streaming parser
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
011e19fd41
commit
1e3f88010f
@ -19,7 +19,6 @@ RFC 4271 BGP-4
|
||||
"""
|
||||
|
||||
# todo
|
||||
# - streaming parser
|
||||
# - notify data
|
||||
# - notify subcode constants
|
||||
# - RFC 1997 BGP Communities Attribute
|
||||
@ -35,6 +34,7 @@ import struct
|
||||
from ryu.ofproto.ofproto_parser import msg_pack_into
|
||||
from ryu.lib.stringify import StringifyMixin
|
||||
from ryu.lib.packet import packet_base
|
||||
from ryu.lib.packet import stream_parser
|
||||
from ryu.lib import addrconv
|
||||
|
||||
|
||||
@ -225,11 +225,20 @@ class BGPMessage(packet_base.PacketBase):
|
||||
|
||||
@classmethod
|
||||
def parser(cls, buf):
|
||||
if len(buf) < cls._HDR_LEN:
|
||||
raise stream_parser.StreamParser.TooSmallException(
|
||||
'%d < %d' % (len(buf), cls._HDR_LEN))
|
||||
(marker, len_, type_) = struct.unpack_from(cls._HDR_PACK_STR,
|
||||
buffer(buf))
|
||||
msglen = len_
|
||||
if len(buf) < msglen:
|
||||
raise stream_parser.StreamParser.TooSmallException(
|
||||
'%d < %d' % (len(buf), msglen))
|
||||
binmsg = buf[cls._HDR_LEN:msglen]
|
||||
rest = buf[msglen:]
|
||||
subcls = cls._TYPES[type_]
|
||||
kwargs = subcls.parser(buf[cls._HDR_LEN:])
|
||||
return subcls(marker=marker, len_=len_, type_=type_, **kwargs)
|
||||
kwargs = subcls.parser(binmsg)
|
||||
return subcls(marker=marker, len_=len_, type_=type_, **kwargs), rest
|
||||
|
||||
def serialize(self):
|
||||
# fixup
|
||||
@ -517,3 +526,14 @@ class BGPNotification(BGPMessage):
|
||||
self.error_subcode))
|
||||
msg += self.data
|
||||
return msg
|
||||
|
||||
|
||||
class StreamParser(stream_parser.StreamParser):
|
||||
"""Streaming parser for BGP-4 messages.
|
||||
|
||||
This is a subclass of ryu.lib.packet.stream_parser.StreamParser.
|
||||
Its parse method returns a list of BGPMessage subclass instances.
|
||||
"""
|
||||
|
||||
def try_parse(self, data):
|
||||
return BGPMessage.parser(data)
|
||||
|
@ -34,25 +34,28 @@ class Test_bgp(unittest.TestCase):
|
||||
def test_open1(self):
|
||||
msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.1')
|
||||
binmsg = msg.serialize()
|
||||
msg2 = bgp.BGPMessage.parser(binmsg)
|
||||
msg2, rest = bgp.BGPMessage.parser(binmsg)
|
||||
eq_(str(msg), str(msg2))
|
||||
eq_(len(msg), 29)
|
||||
eq_(rest, '')
|
||||
|
||||
def test_open2(self):
|
||||
msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2',
|
||||
opt_param=[bgp.BGPOptParam(type_=1, value='hooge'),
|
||||
bgp.BGPOptParam(type_=2, value='fuga')])
|
||||
binmsg = msg.serialize()
|
||||
msg2 = bgp.BGPMessage.parser(binmsg)
|
||||
msg2, rest = bgp.BGPMessage.parser(binmsg)
|
||||
eq_(str(msg), str(msg2))
|
||||
ok_(len(msg) > 29)
|
||||
eq_(rest, '')
|
||||
|
||||
def test_update1(self):
|
||||
msg = bgp.BGPUpdate()
|
||||
binmsg = msg.serialize()
|
||||
msg2 = bgp.BGPMessage.parser(binmsg)
|
||||
msg2, rest = bgp.BGPMessage.parser(binmsg)
|
||||
eq_(str(msg), str(msg2))
|
||||
eq_(len(msg), 23)
|
||||
eq_(rest, '')
|
||||
|
||||
def test_update2(self):
|
||||
withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0,
|
||||
@ -76,21 +79,38 @@ class Test_bgp(unittest.TestCase):
|
||||
path_attributes=path_attributes,
|
||||
nlri=nlri)
|
||||
binmsg = msg.serialize()
|
||||
msg2 = bgp.BGPMessage.parser(binmsg)
|
||||
msg2, rest = bgp.BGPMessage.parser(binmsg)
|
||||
eq_(str(msg), str(msg2))
|
||||
ok_(len(msg) > 23)
|
||||
eq_(rest, '')
|
||||
|
||||
def test_keepalive(self):
|
||||
msg = bgp.BGPKeepAlive()
|
||||
binmsg = msg.serialize()
|
||||
msg2 = bgp.BGPMessage.parser(binmsg)
|
||||
msg2, rest = bgp.BGPMessage.parser(binmsg)
|
||||
eq_(str(msg), str(msg2))
|
||||
eq_(len(msg), 19)
|
||||
eq_(rest, '')
|
||||
|
||||
def test_notification(self):
|
||||
data = "hoge"
|
||||
msg = bgp.BGPNotification(error_code=1, error_subcode=2, data=data)
|
||||
binmsg = msg.serialize()
|
||||
msg2 = bgp.BGPMessage.parser(binmsg)
|
||||
msg2, rest = bgp.BGPMessage.parser(binmsg)
|
||||
eq_(str(msg), str(msg2))
|
||||
eq_(len(msg), 21 + len(data))
|
||||
eq_(rest, '')
|
||||
|
||||
def test_stream_parser(self):
|
||||
msgs = [
|
||||
bgp.BGPNotification(error_code=1, error_subcode=2, data="foo"),
|
||||
bgp.BGPNotification(error_code=3, error_subcode=4, data="bar"),
|
||||
bgp.BGPNotification(error_code=5, error_subcode=6, data="baz"),
|
||||
]
|
||||
binmsgs = ''.join([bytes(msg.serialize()) for msg in msgs])
|
||||
sp = bgp.StreamParser()
|
||||
results = []
|
||||
for b in binmsgs:
|
||||
for m in sp.parse(b):
|
||||
results.append(m)
|
||||
eq_(str(results), str(msgs))
|
||||
|
Loading…
x
Reference in New Issue
Block a user