packet/bgp: Enable to parse the entire packet data

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.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
IWASE Yusuke 2016-08-22 17:21:23 +09:00 committed by FUJITA Tomonori
parent d4b8bd609f
commit 0255390a76
5 changed files with 36 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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,