From 82b113afb68283bd49f0e114823a3ba5c12c929d Mon Sep 17 00:00:00 2001 From: Shinpei Muraoka Date: Thu, 12 Jan 2017 17:05:22 +0900 Subject: [PATCH] packet lib: Add packet library of OpenFlow Signed-off-by: Shinpei Muraoka Signed-off-by: FUJITA Tomonori --- ryu/lib/packet/openflow.py | 113 +++++++++++++++++++++++++++++++++++++ ryu/lib/packet/tcp.py | 5 ++ 2 files changed, 118 insertions(+) create mode 100644 ryu/lib/packet/openflow.py diff --git a/ryu/lib/packet/openflow.py b/ryu/lib/packet/openflow.py new file mode 100644 index 00000000..e2119941 --- /dev/null +++ b/ryu/lib/packet/openflow.py @@ -0,0 +1,113 @@ +# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import struct + +from ryu.lib import stringify +from . import packet_base + + +class openflow(packet_base.PacketBase): + """OpenFlow message encoder/decoder class. + + An instance has the following attributes at least. + + ============== ========================================================= + Attribute Description + ============== ========================================================= + msg An instance of OpenFlow message (see :ref:`ofproto_ref`) + or an instance of OFPUnparseableMsg if failed to parse + packet as OpenFlow message. + ============== ========================================================= + """ + + PACK_STR = '!BBHI' + _MIN_LEN = struct.calcsize(PACK_STR) + + def __init__(self, msg): + super(openflow, self).__init__() + self.msg = msg + + @classmethod + def parser(cls, buf): + from ryu.ofproto import ofproto_parser + from ryu.ofproto import ofproto_protocol + + (version, msg_type, msg_len, xid) = ofproto_parser.header(buf) + + msg_parser = ofproto_parser._MSG_PARSERS.get(version) + if msg_parser is None: + msg = OFPUnparseableMsg( + None, version, msg_type, msg_len, xid, + buf[cls._MIN_LEN:msg_len]) + return cls(msg), cls, buf[msg_len:] + + datapath = ofproto_protocol.ProtocolDesc(version=version) + + try: + msg = msg_parser(datapath, version, msg_type, msg_len, xid, + buf[:msg_len]) + except: + msg = OFPUnparseableMsg( + datapath, version, msg_type, msg_len, xid, + buf[datapath.ofproto.OFP_HEADER_SIZE:msg_len]) + + return cls(msg), cls, buf[msg_len:] + + def serialize(self, _payload, _prev): + self.msg.serialize() + return self.msg.buf + + +class OFPUnparseableMsg(stringify.StringifyMixin): + """Unparseable OpenFlow message encoder class. + + An instance has the following attributes at least. + + ============== ====================================================== + Attribute Description + ============== ====================================================== + datapath A ryu.ofproto.ofproto_protocol.ProtocolDesc instance + for this message or None if OpenFlow protocol version + is unsupported version. + version OpenFlow protocol version + msg_type Type of OpenFlow message + msg_len Length of the message + xid Transaction id + body OpenFlow body data + ============== ====================================================== + + .. Note:: + + "datapath" attribute is different from + ryu.controller.controller.Datapath. + So you can not use "datapath" attribute to send OpenFlow messages. + For example, "datapath" attribute does not have send_msg method. + """ + + def __init__(self, datapath, version, msg_type, msg_len, xid, body): + self.datapath = datapath + self.version = version + self.msg_type = msg_type + self.msg_len = msg_len + self.xid = xid + self.body = body + self.buf = None + + def serialize(self): + self.buf = struct.pack( + openflow.PACK_STR, + self.version, self.msg_type, self.msg_len, self.xid) + self.buf += self.body diff --git a/ryu/lib/packet/tcp.py b/ryu/lib/packet/tcp.py index b61ac8cf..a58a2d09 100644 --- a/ryu/lib/packet/tcp.py +++ b/ryu/lib/packet/tcp.py @@ -20,6 +20,7 @@ import logging from . import packet_base from . import packet_utils from . import bgp +from . import openflow from ryu.lib import stringify @@ -111,8 +112,12 @@ class tcp(packet_base.PacketBase): @staticmethod def get_payload_type(src_port, dst_port): + from ryu.ofproto.ofproto_common import OFP_TCP_PORT, OFP_SSL_PORT_OLD if bgp.TCP_SERVER_PORT in [src_port, dst_port]: return bgp.BGPMessage + elif(src_port in [OFP_TCP_PORT, OFP_SSL_PORT_OLD] or + dst_port in [OFP_TCP_PORT, OFP_SSL_PORT_OLD]): + return openflow.openflow else: return None