---
ryu/lib/packet/bgp.py | 26 +++++++++++++++++++++++---
ryu/tests/unit/packet/test_bgp.py | 32 ++++++++++++++++++++++++++------
2 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index a6d5f4d..4c2119c 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -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)
diff --git a/ryu/tests/unit/packet/test_bgp.py
b/ryu/tests/unit/packet/test_bgp.py
index db5319d..808b2db 100644
--- a/ryu/tests/unit/packet/test_bgp.py
+++ b/ryu/tests/unit/packet/test_bgp.py
@@ -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))
--
1.8.3.1
------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60133471&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel