This patch fixes the TCP packet parser to return the BGP packet
parser class if the TCP src or dst port is the reserved BGP port
and enable to parse the entire packet data.

Signed-off-by: IWASE Yusuke <iwase.yusu...@gmail.com>
---
 ryu/lib/packet/bgp.py                 |  8 ++++++--
 ryu/lib/packet/bmp.py                 | 10 +++++-----
 ryu/lib/packet/tcp.py                 | 10 +++++++++-
 ryu/services/protocols/bgp/speaker.py |  2 +-
 ryu/tests/unit/packet/test_bgp.py     | 27 +++++++++++++++------------
 5 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index 68105a8..99da867 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -41,6 +41,8 @@ from ryu.lib.pack_utils import msg_pack_into
 
 reduce = six.moves.reduce
 
+TCP_SERVER_PORT = 179
+
 BGP_MSG_OPEN = 1
 BGP_MSG_UPDATE = 2
 BGP_MSG_NOTIFICATION = 3
@@ -2238,7 +2240,8 @@ class BGPMessage(packet_base.PacketBase, _TypeDisp):
         rest = buf[msglen:]
         subcls = cls._lookup_type(type_)
         kwargs = subcls.parser(binmsg)
-        return subcls(marker=marker, len_=len_, type_=type_, **kwargs), rest
+        return subcls(marker=marker, len_=len_, type_=type_,
+                      **kwargs), None, rest
 
     def serialize(self, payload=None, prev=None):
         # fixup
@@ -2661,4 +2664,5 @@ class StreamParser(stream_parser.StreamParser):
     """
 
     def try_parse(self, data):
-        return BGPMessage.parser(data)
+        msg, _, rest = BGPMessage.parser(data)
+        return msg, rest
diff --git a/ryu/lib/packet/bmp.py b/ryu/lib/packet/bmp.py
index c25e574..b3a097c 100644
--- a/ryu/lib/packet/bmp.py
+++ b/ryu/lib/packet/bmp.py
@@ -327,7 +327,7 @@ class BMPRouteMonitoring(BMPPeerMessage):
     def parser(cls, buf):
         kwargs, buf = super(BMPRouteMonitoring, cls).parser(buf)
 
-        bgp_update, buf = BGPMessage.parser(buf)
+        bgp_update, _, buf = BGPMessage.parser(buf)
 
         kwargs['bgp_update'] = bgp_update
 
@@ -498,11 +498,11 @@ class BMPPeerDownNotification(BMPPeerMessage):
         buf = buf[struct.calcsize('!B'):]
 
         if reason == BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION:
-            data, rest = BGPMessage.parser(buf)
+            data, _, rest = BGPMessage.parser(buf)
         elif reason == BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION:
             data = struct.unpack_from('!H', six.binary_type(buf))
         elif reason == BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
-            data, rest = BGPMessage.parser(buf)
+            data, _, rest = BGPMessage.parser(buf)
         elif reason == BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION:
             data = None
         else:
@@ -609,8 +609,8 @@ class BMPPeerUpNotification(BMPPeerMessage):
 
         rest = rest[cls._MIN_LEN:]
 
-        sent_open_msg, rest = BGPMessage.parser(rest)
-        received_open_msg, rest = BGPMessage.parser(rest)
+        sent_open_msg, _, rest = BGPMessage.parser(rest)
+        received_open_msg, _, rest = BGPMessage.parser(rest)
 
         kwargs['sent_open_message'] = sent_open_msg
         kwargs['received_open_message'] = received_open_msg
diff --git a/ryu/lib/packet/tcp.py b/ryu/lib/packet/tcp.py
index 1771b9a..b61ac8c 100644
--- a/ryu/lib/packet/tcp.py
+++ b/ryu/lib/packet/tcp.py
@@ -19,6 +19,7 @@ import logging
 
 from . import packet_base
 from . import packet_utils
+from . import bgp
 from ryu.lib import stringify
 
 
@@ -108,6 +109,13 @@ class tcp(packet_base.PacketBase):
         mask = sum(flags)
         return (self.bits & mask) == mask
 
+    @staticmethod
+    def get_payload_type(src_port, dst_port):
+        if bgp.TCP_SERVER_PORT in [src_port, dst_port]:
+            return bgp.BGPMessage
+        else:
+            return None
+
     @classmethod
     def parser(cls, buf):
         (src_port, dst_port, seq, ack, offset, bits, window_size,
@@ -132,7 +140,7 @@ class tcp(packet_base.PacketBase):
         msg = cls(src_port, dst_port, seq, ack, offset, bits,
                   window_size, csum, urgent, option)
 
-        return msg, None, buf[length:]
+        return msg, cls.get_payload_type(src_port, dst_port), buf[length:]
 
     def serialize(self, payload, prev):
         offset = self.offset << 4
diff --git a/ryu/services/protocols/bgp/speaker.py 
b/ryu/services/protocols/bgp/speaker.py
index 9c185da..710efa7 100644
--- a/ryu/services/protocols/bgp/speaker.py
+++ b/ryu/services/protocols/bgp/speaker.py
@@ -350,7 +350,7 @@ class BgpProtocol(Protocol, Activity):
             # If we have partial message we wait for rest of the message.
             if len(self._recv_buff) < length:
                 return
-            msg, rest = BGPMessage.parser(self._recv_buff)
+            msg, _, rest = BGPMessage.parser(self._recv_buff)
             self._recv_buff = rest
 
             # If we have a valid bgp message we call message handler.
diff --git a/ryu/tests/unit/packet/test_bgp.py 
b/ryu/tests/unit/packet/test_bgp.py
index b3c1198..d23b259 100644
--- a/ryu/tests/unit/packet/test_bgp.py
+++ b/ryu/tests/unit/packet/test_bgp.py
@@ -22,6 +22,7 @@ import unittest
 from nose.tools import eq_
 from nose.tools import ok_
 
+from ryu.lib import pcaplib
 from ryu.lib.packet import packet
 from ryu.lib.packet import bgp
 from ryu.lib.packet import afi
@@ -45,7 +46,7 @@ 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, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         eq_(len(msg), 29)
         eq_(rest, b'')
@@ -67,7 +68,7 @@ class Test_bgp(unittest.TestCase):
         msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2',
                           opt_param=opt_param)
         binmsg = msg.serialize()
-        msg2, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         ok_(len(msg) > 29)
         eq_(rest, b'')
@@ -75,7 +76,7 @@ class Test_bgp(unittest.TestCase):
     def test_update1(self):
         msg = bgp.BGPUpdate()
         binmsg = msg.serialize()
-        msg2, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         eq_(len(msg), 23)
         eq_(rest, b'')
@@ -153,7 +154,7 @@ class Test_bgp(unittest.TestCase):
                             path_attributes=path_attributes,
                             nlri=nlri)
         binmsg = msg.serialize()
-        msg2, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         ok_(len(msg) > 23)
         eq_(rest, b'')
@@ -161,7 +162,7 @@ class Test_bgp(unittest.TestCase):
     def test_keepalive(self):
         msg = bgp.BGPKeepAlive()
         binmsg = msg.serialize()
-        msg2, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         eq_(len(msg), 19)
         eq_(rest, b'')
@@ -170,7 +171,7 @@ class Test_bgp(unittest.TestCase):
         data = b'hoge'
         msg = bgp.BGPNotification(error_code=1, error_subcode=2, data=data)
         binmsg = msg.serialize()
-        msg2, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         eq_(len(msg), 21 + len(data))
         eq_(rest, b'')
@@ -178,7 +179,7 @@ class Test_bgp(unittest.TestCase):
     def test_route_refresh(self):
         msg = bgp.BGPRouteRefresh(afi=afi.IP, safi=safi.MPLS_VPN)
         binmsg = msg.serialize()
-        msg2, rest = bgp.BGPMessage.parser(binmsg)
+        msg2, _, rest = bgp.BGPMessage.parser(binmsg)
         eq_(str(msg), str(msg2))
         eq_(len(msg), 23)
         eq_(rest, b'')
@@ -208,11 +209,13 @@ class Test_bgp(unittest.TestCase):
         ]
 
         for f in files:
-            print('testing %s' % f)
-            msg_buf = open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb').read()
-            pkt = packet.Packet(msg_buf)
-            pkt.serialize()
-            eq_(msg_buf, pkt.data)
+            print('\n*** testing %s ...' % f)
+            for _, buf in pcaplib.Reader(
+                    open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb')):
+                pkt = packet.Packet(buf)
+                print(pkt)
+                pkt.serialize()
+                eq_(buf, pkt.data)
 
     def test_json1(self):
         opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200,
-- 
2.7.4


------------------------------------------------------------------------------
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to