This patch adds a test framework using mininet. The following tests can be 
performed.

- Set the flow for the OVS-switch from Ryu-app, we test the actual packet is to 
be 
  handled properly in accordance with the flow; The packet that generated by 
"mz"
  or replayed by "tcpreplay" is routed through the ovs-switch, are processed
  according to the flow, then compare test conditions and the results captured
  by "tshark".

- Create a packet with ryu using the packet-lib, we test the packet and response
  are correct; to compare test conditions and the results captured by "tshark".
  
  
On Mon, 28 Jan 2013 16:01:22 +0900
HIYAMA Manabu <[email protected]> wrote:

>   $ ./run_mnet-test.sh [OPTION] [TEST DIR or FILE]...
>   $ ./run_mnet-test.sh l2 l3/icmp packet_lib/arp/ARP_gratuitous.mn
>   $ ./run_mnet-test.sh --help
> 
> Requirements package:
>  - mininet: git://github.com/mininet/mininet.git
>  - openvswitch: git://openvswitch.org/openvswitch
>  - Mausezahn 0.40: http://www.perihel.at/sec/mz/
>  - TShark 1.6.2: http://www.wireshark.org/
>  - tcpreplay 3.4: http://tcpreplay.synfin.net/
> 
> Signed-off-by: HIYAMA Manabu <[email protected]>
> ---
>  ryu/tests/mininet/l2/mpls/PopMPLS_mpls.mn          |    6 +
>  ryu/tests/mininet/l2/mpls/PushMPLS_ip.mn           |    6 +
>  ryu/tests/mininet/l2/mpls/PushMPLS_mpls.mn         |    6 +
>  ryu/tests/mininet/l2/mpls/test_mpls.py             |  128 +++++++++
>  ryu/tests/mininet/l2/vlan/PopVLAN_vlan.mn          |    6 +
>  ryu/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn      |    6 +
>  ryu/tests/mininet/l2/vlan/PushVLAN_icmp.mn         |    6 +
>  ryu/tests/mininet/l2/vlan/test_vlan.py             |  131 ++++++++++
>  ryu/tests/mininet/l3/icmp/ICMP_ping.mn             |    6 +
>  ryu/tests/mininet/l3/icmp/ICMP_reply.mn            |    6 +
>  ryu/tests/mininet/l3/icmp/test_icmp.py             |   85 ++++++
>  ryu/tests/mininet/l3/ip_ttl/DecNwTtl.mn            |    6 +
>  ryu/tests/mininet/l3/ip_ttl/test_ip_ttl.py         |   85 ++++++
>  ryu/tests/mininet/packet_lib/arp/ARP_gratuitous.mn |    7 +
>  ryu/tests/mininet/packet_lib/arp/ARP_reply.mn      |    7 +
>  ryu/tests/mininet/packet_lib/arp/ARP_request.mn    |    7 +
>  ryu/tests/mininet/packet_lib/arp/test_arp.py       |  199 ++++++++++++++
>  ryu/tests/mininet/run_mnet-test.sh                 |  274 
> ++++++++++++++++++++
>  18 files changed, 977 insertions(+)
>  create mode 100644 ryu/tests/mininet/l2/mpls/PopMPLS_mpls.mn
>  create mode 100644 ryu/tests/mininet/l2/mpls/PushMPLS_ip.mn
>  create mode 100644 ryu/tests/mininet/l2/mpls/PushMPLS_mpls.mn
>  create mode 100644 ryu/tests/mininet/l2/mpls/test_mpls.py
>  create mode 100644 ryu/tests/mininet/l2/vlan/PopVLAN_vlan.mn
>  create mode 100644 ryu/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn
>  create mode 100644 ryu/tests/mininet/l2/vlan/PushVLAN_icmp.mn
>  create mode 100644 ryu/tests/mininet/l2/vlan/test_vlan.py
>  create mode 100644 ryu/tests/mininet/l3/icmp/ICMP_ping.mn
>  create mode 100644 ryu/tests/mininet/l3/icmp/ICMP_reply.mn
>  create mode 100644 ryu/tests/mininet/l3/icmp/test_icmp.py
>  create mode 100644 ryu/tests/mininet/l3/ip_ttl/DecNwTtl.mn
>  create mode 100644 ryu/tests/mininet/l3/ip_ttl/test_ip_ttl.py
>  create mode 100644 ryu/tests/mininet/packet_lib/arp/ARP_gratuitous.mn
>  create mode 100644 ryu/tests/mininet/packet_lib/arp/ARP_reply.mn
>  create mode 100644 ryu/tests/mininet/packet_lib/arp/ARP_request.mn
>  create mode 100644 ryu/tests/mininet/packet_lib/arp/test_arp.py
>  create mode 100755 ryu/tests/mininet/run_mnet-test.sh
> 
> diff --git a/ryu/tests/mininet/l2/mpls/PopMPLS_mpls.mn 
> b/ryu/tests/mininet/l2/mpls/PopMPLS_mpls.mn
> new file mode 100644
> index 0000000..45fa9f9
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/mpls/PopMPLS_mpls.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=MPLS-PopMPLS
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_mpls
> +PCAP_MZ="-t tcp -M 80 -P $TEST_NAME -c 3 -r"
> +PCAP_FILTER="! mpls && ip.proto==TCP"
> diff --git a/ryu/tests/mininet/l2/mpls/PushMPLS_ip.mn 
> b/ryu/tests/mininet/l2/mpls/PushMPLS_ip.mn
> new file mode 100644
> index 0000000..2634e78
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/mpls/PushMPLS_ip.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=IP-PushMPLS
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_mpls
> +PCAP_MZ="-t tcp -P $TEST_NAME -c 3 -b 00:00:00:00:00:02"
> +PCAP_FILTER="mpls && ip.proto==TCP"
> diff --git a/ryu/tests/mininet/l2/mpls/PushMPLS_mpls.mn 
> b/ryu/tests/mininet/l2/mpls/PushMPLS_mpls.mn
> new file mode 100644
> index 0000000..5ac1702
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/mpls/PushMPLS_mpls.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=MPLS-PushMPLS
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_mpls
> +PCAP_MZ="-t tcp -M 100 -P $TEST_NAME -c 3 -r"
> +PCAP_FILTER="mpls.label==100 && mpls.label==200 && ip.proto==TCP"
> diff --git a/ryu/tests/mininet/l2/mpls/test_mpls.py 
> b/ryu/tests/mininet/l2/mpls/test_mpls.py
> new file mode 100644
> index 0000000..c055ea2
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/mpls/test_mpls.py
> @@ -0,0 +1,128 @@
> +# Copyright (C) 2012 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 logging
> +import struct
> +
> +from ryu.base import app_manager
> +from ryu.controller import ofp_event
> +from ryu.controller import dpset
> +from ryu.controller.handler import MAIN_DISPATCHER
> +from ryu.controller.handler import set_ev_cls
> +from ryu.ofproto import ofproto_v1_2
> +from ryu.ofproto import ether
> +from ryu.lib.mac import haddr_to_str
> +
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class RunTestMininet(app_manager.RyuApp):
> +
> +    _CONTEXTS = {'dpset': dpset.DPSet}
> +    OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]
> +
> +    def __init__(self, *args, **kwargs):
> +        super(RunTestMininet, self).__init__(*args, **kwargs)
> +        self.mac_to_port = {}
> +
> +    def _add_flow(self, dp, match, actions):
> +        inst = [dp.ofproto_parser.OFPInstructionActions(
> +            dp.ofproto.OFPIT_APPLY_ACTIONS, actions)]
> +
> +        mod = dp.ofproto_parser.OFPFlowMod(
> +            dp, cookie=0, cookie_mask=0, table_id=0,
> +            command=dp.ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
> +            priority=0xff, buffer_id=0xffffffff,
> +            out_port=dp.ofproto.OFPP_ANY, out_group=dp.ofproto.OFPG_ANY,
> +            flags=0, match=match, instructions=inst)
> +
> +        dp.send_msg(mod)
> +
> +    def _define_flow(self, dp):
> +        in_port = 1
> +        out_port = 2
> +
> +        eth_IP = ether.ETH_TYPE_IP
> +        eth_MPLS = ether.ETH_TYPE_MPLS
> +
> +        # MPLS(80) -> PopMPLS
> +        LOG.debug("--- add_flow PopMPLS")
> +        m_label = 80
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_MPLS)
> +        match.set_mpls_label(m_label)
> +        actions = [dp.ofproto_parser.OFPActionPopMpls(eth_IP),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +        # IP -> PushMPLS(90)
> +        LOG.debug("--- add_flow PushMPLS")
> +        s_label = 90
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_IP)
> +        f = dp.ofproto_parser.OFPMatchField.make(
> +            dp.ofproto.OXM_OF_MPLS_LABEL, s_label)
> +        actions = [dp.ofproto_parser.OFPActionPushMpls(eth_MPLS),
> +                   dp.ofproto_parser.OFPActionSetField(f),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +        # MPLS(100) -> PushMPLS(200)
> +        LOG.debug("--- add_flow PushMPLS")
> +        m_label = 100
> +        s_label = 200
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_MPLS)
> +        match.set_mpls_label(m_label)
> +        f = dp.ofproto_parser.OFPMatchField.make(
> +            dp.ofproto.OXM_OF_MPLS_LABEL, s_label)
> +        actions = [dp.ofproto_parser.OFPActionPushMpls(eth_MPLS),
> +                   dp.ofproto_parser.OFPActionSetField(f),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +        # MPLS(1000):MPLS -> PopMPLS
> +        # LOG.debug("--- add_flow PopMPLS")
> +        # SKIP: ovs not supported
> +        m_label = 1000
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_MPLS)
> +        match.set_mpls_label(m_label)
> +        actions = [dp.ofproto_parser.OFPActionPopMpls(eth_MPLS),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        # self._add_flow(dp, match, actions)
> +
> +    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
> +    def handler_datapath(self, ev):
> +        if ev.enter:
> +            self._define_flow(ev.dp)
> +
> +    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
> +    def packet_in_handler(self, ev):
> +        msg = ev.msg
> +        dst, src, eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 
> 0)
> +        in_port = msg.match.fields[0].value
> +
> +        LOG.info("----------------------------------------")
> +        LOG.info("* PacketIn")
> +        LOG.info("in_port=%d, eth_type: %s", in_port, hex(eth_type))
> +        LOG.info("packet reason=%d buffer_id=%d", msg.reason, msg.buffer_id)
> +        LOG.info("packet in datapath_id=%s src=%s dst=%s",
> +                 msg.datapath.id, haddr_to_str(src), haddr_to_str(dst))
> diff --git a/ryu/tests/mininet/l2/vlan/PopVLAN_vlan.mn 
> b/ryu/tests/mininet/l2/vlan/PopVLAN_vlan.mn
> new file mode 100644
> index 0000000..f1d1c6d
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/vlan/PopVLAN_vlan.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=VLAN-PopVLAN
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_vlan
> +PCAP_MZ="-t tcp -Q 8 -P $TEST_NAME -c 3 -r"
> +PCAP_FILTER="! vlan && ip.proto==TCP"
> diff --git a/ryu/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn 
> b/ryu/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn
> new file mode 100644
> index 0000000..90444a7
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=VLAN:VLAN-PopVLAN
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_vlan
> +PCAP_MZ="-t tcp -Q 100,99 -P $TEST_NAME -c 3 -r"
> +PCAP_FILTER="vlan.id!=100 && vlan.id==99 && ip.proto==TCP"
> diff --git a/ryu/tests/mininet/l2/vlan/PushVLAN_icmp.mn 
> b/ryu/tests/mininet/l2/vlan/PushVLAN_icmp.mn
> new file mode 100644
> index 0000000..439ad23
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/vlan/PushVLAN_icmp.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=ICMP-PushVLAN
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_vlan
> +PCAP_MZ="-t icmp ping -P $TEST_NAME -c 3 -r -b 00:00:00:00:00:02"
> +PCAP_FILTER="vlan && icmp.type==8"
> diff --git a/ryu/tests/mininet/l2/vlan/test_vlan.py 
> b/ryu/tests/mininet/l2/vlan/test_vlan.py
> new file mode 100644
> index 0000000..beb7169
> --- /dev/null
> +++ b/ryu/tests/mininet/l2/vlan/test_vlan.py
> @@ -0,0 +1,131 @@
> +# Copyright (C) 2012 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 logging
> +import struct
> +
> +from ryu.base import app_manager
> +from ryu.controller import ofp_event
> +from ryu.controller import dpset
> +from ryu.controller.handler import MAIN_DISPATCHER
> +from ryu.controller.handler import set_ev_cls
> +from ryu.ofproto import ofproto_v1_2
> +from ryu.ofproto import ether
> +from ryu.ofproto import inet
> +from ryu.lib.mac import haddr_to_str
> +
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class RunTestMininet(app_manager.RyuApp):
> +
> +    _CONTEXTS = {'dpset': dpset.DPSet}
> +    OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]
> +
> +    def __init__(self, *args, **kwargs):
> +        super(RunTestMininet, self).__init__(*args, **kwargs)
> +        self.mac_to_port = {}
> +
> +    def _add_flow(self, dp, match, actions):
> +        inst = [dp.ofproto_parser.OFPInstructionActions(
> +            dp.ofproto.OFPIT_APPLY_ACTIONS, actions)]
> +
> +        mod = dp.ofproto_parser.OFPFlowMod(
> +            dp, cookie=0, cookie_mask=0, table_id=0,
> +            command=dp.ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
> +            priority=0xff, buffer_id=0xffffffff,
> +            out_port=dp.ofproto.OFPP_ANY, out_group=dp.ofproto.OFPG_ANY,
> +            flags=0, match=match, instructions=inst)
> +
> +        dp.send_msg(mod)
> +
> +    def _define_flow(self, dp):
> +        in_port = 1
> +        out_port = 2
> +
> +        eth_IP = ether.ETH_TYPE_IP
> +        eth_VLAN = ether.ETH_TYPE_8021Q
> +        ip_ICMP = inet.IPPROTO_ICMP
> +
> +        # VLAN(8) -> PopVLAN
> +        LOG.debug("--- add_flow VLAN(8) to PopVLAN")
> +        m_vid = 8
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_IP)
> +        match.set_vlan_vid(m_vid)
> +        actions = [dp.ofproto_parser.OFPActionPopVlan(),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +        # ICMP -> PushVLAN(9)
> +        LOG.debug("--- add_flow ICMP to PushVLAN(9)")
> +        s_vid = 9
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_IP)
> +        match.set_ip_proto(ip_ICMP)
> +        f = dp.ofproto_parser.OFPMatchField.make(
> +            dp.ofproto.OXM_OF_VLAN_VID, s_vid)
> +        actions = [dp.ofproto_parser.OFPActionPushVlan(eth_VLAN),
> +                   dp.ofproto_parser.OFPActionSetField(f),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +        # VLAN(10) -> PushVLAN(20)
> +        # LOG.debug("--- add_flow VLAN(10) to PushVLAN(100)")
> +        # SKIP: ovs not supported
> +        m_vid = 10
> +        s_vid = 20
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_IP)
> +        match.set_vlan_vid(m_vid)
> +        f = dp.ofproto_parser.OFPMatchField.make(
> +            dp.ofproto.OXM_OF_VLAN_VID, s_vid)
> +        actions = [dp.ofproto_parser.OFPActionPushVlan(eth_VLAN),
> +                   dp.ofproto_parser.OFPActionSetField(f),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        # self._add_flow(dp, match, actions)
> +
> +        # VLAN(100):VLAN -> PopVLAN
> +        LOG.debug("--- add_flow VLAN(100):VLAN to PopVLAN")
> +        m_vid = 100
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_VLAN)
> +        match.set_vlan_vid(m_vid)
> +        actions = [dp.ofproto_parser.OFPActionPopVlan(),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
> +    def handler_datapath(self, ev):
> +        if ev.enter:
> +            self._define_flow(ev.dp)
> +
> +    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
> +    def packet_in_handler(self, ev):
> +        msg = ev.msg
> +        dst, src, eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 
> 0)
> +        in_port = msg.match.fields[0].value
> +
> +        LOG.info("----------------------------------------")
> +        LOG.info("* PacketIn")
> +        LOG.info("in_port=%d, eth_type: %s", in_port, hex(eth_type))
> +        LOG.info("packet reason=%d buffer_id=%d", msg.reason, msg.buffer_id)
> +        LOG.info("packet in datapath_id=%s src=%s dst=%s",
> +                 msg.datapath.id, haddr_to_str(src), haddr_to_str(dst))
> diff --git a/ryu/tests/mininet/l3/icmp/ICMP_ping.mn 
> b/ryu/tests/mininet/l3/icmp/ICMP_ping.mn
> new file mode 100644
> index 0000000..f558693
> --- /dev/null
> +++ b/ryu/tests/mininet/l3/icmp/ICMP_ping.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=ICMP-Req
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_icmp
> +PCAP_MZ="-t icmp ping -c 3 -r -b 00:00:00:00:00:00"
> +PCAP_FILTER="icmp.type==8"
> diff --git a/ryu/tests/mininet/l3/icmp/ICMP_reply.mn 
> b/ryu/tests/mininet/l3/icmp/ICMP_reply.mn
> new file mode 100644
> index 0000000..eb6bc8b
> --- /dev/null
> +++ b/ryu/tests/mininet/l3/icmp/ICMP_reply.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=ICMP-Reply
> +DUMP_HOST=h1
> +DUMP_IF=h1-eth0
> +RYU_APP=test_icmp
> +PCAP_MZ="-t icmp ping -c 3 -r -B h2"
> +PCAP_FILTER="icmp.type==0"
> diff --git a/ryu/tests/mininet/l3/icmp/test_icmp.py 
> b/ryu/tests/mininet/l3/icmp/test_icmp.py
> new file mode 100644
> index 0000000..5cf640c
> --- /dev/null
> +++ b/ryu/tests/mininet/l3/icmp/test_icmp.py
> @@ -0,0 +1,85 @@
> +# Copyright (C) 2012 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 logging
> +import struct
> +
> +from ryu.base import app_manager
> +from ryu.controller import ofp_event
> +from ryu.controller import dpset
> +from ryu.controller.handler import MAIN_DISPATCHER
> +from ryu.controller.handler import set_ev_cls
> +from ryu.ofproto import ofproto_v1_2
> +from ryu.lib.mac import haddr_to_str
> +
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class RunTestMininet(app_manager.RyuApp):
> +
> +    _CONTEXTS = {'dpset': dpset.DPSet}
> +    OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]
> +
> +    def __init__(self, *args, **kwargs):
> +        super(RunTestMininet, self).__init__(*args, **kwargs)
> +        self.mac_to_port = {}
> +
> +    def _add_flow(self, dp, match, actions):
> +        inst = [dp.ofproto_parser.OFPInstructionActions(
> +            dp.ofproto.OFPIT_APPLY_ACTIONS, actions)]
> +
> +        mod = dp.ofproto_parser.OFPFlowMod(
> +            dp, cookie=0, cookie_mask=0, table_id=0,
> +            command=dp.ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
> +            priority=0xff, buffer_id=0xffffffff,
> +            out_port=dp.ofproto.OFPP_ANY, out_group=dp.ofproto.OFPG_ANY,
> +            flags=0, match=match, instructions=inst)
> +
> +        dp.send_msg(mod)
> +
> +    def _define_flow(self, dp):
> +        in_port = 1
> +        out_port = 2
> +
> +        # port:1 -> port:2
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        actions = [dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +        # port:1 -> port:2
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(out_port)
> +        actions = [dp.ofproto_parser.OFPActionOutput(in_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
> +    def handler_datapath(self, ev):
> +        if ev.enter:
> +            self._define_flow(ev.dp)
> +
> +    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
> +    def packet_in_handler(self, ev):
> +        msg = ev.msg
> +        dst, src, eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 
> 0)
> +        in_port = msg.match.fields[0].value
> +
> +        LOG.info("----------------------------------------")
> +        LOG.info("* PacketIn")
> +        LOG.info("in_port=%d, eth_type: %s", in_port, hex(eth_type))
> +        LOG.info("packet reason=%d buffer_id=%d", msg.reason, msg.buffer_id)
> +        LOG.info("packet in datapath_id=%s src=%s dst=%s",
> +                 msg.datapath.id, haddr_to_str(src), haddr_to_str(dst))
> diff --git a/ryu/tests/mininet/l3/ip_ttl/DecNwTtl.mn 
> b/ryu/tests/mininet/l3/ip_ttl/DecNwTtl.mn
> new file mode 100644
> index 0000000..60cd462
> --- /dev/null
> +++ b/ryu/tests/mininet/l3/ip_ttl/DecNwTtl.mn
> @@ -0,0 +1,6 @@
> +TEST_NAME=DecNwTtl
> +DUMP_HOST=h2
> +DUMP_IF=h2-eth0
> +RYU_APP=test_ip_ttl
> +PCAP_MZ="-t icmp ttl=64 -P $TEST_NAME -c 3 -b 00:00:00:00:00:02"
> +PCAP_FILTER="icmp && ip.ttl==63"
> diff --git a/ryu/tests/mininet/l3/ip_ttl/test_ip_ttl.py 
> b/ryu/tests/mininet/l3/ip_ttl/test_ip_ttl.py
> new file mode 100644
> index 0000000..5ebc643
> --- /dev/null
> +++ b/ryu/tests/mininet/l3/ip_ttl/test_ip_ttl.py
> @@ -0,0 +1,85 @@
> +# Copyright (C) 2012 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 logging
> +import struct
> +
> +from ryu.base import app_manager
> +from ryu.controller import ofp_event
> +from ryu.controller import dpset
> +from ryu.controller.handler import MAIN_DISPATCHER
> +from ryu.controller.handler import set_ev_cls
> +from ryu.ofproto import ofproto_v1_2
> +from ryu.ofproto import ether
> +from ryu.lib.mac import haddr_to_str
> +
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class RunTestMininet(app_manager.RyuApp):
> +
> +    _CONTEXTS = {'dpset': dpset.DPSet}
> +    OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]
> +
> +    def __init__(self, *args, **kwargs):
> +        super(RunTestMininet, self).__init__(*args, **kwargs)
> +        self.mac_to_port = {}
> +
> +    def _add_flow(self, dp, match, actions):
> +        inst = [dp.ofproto_parser.OFPInstructionActions(
> +            dp.ofproto.OFPIT_APPLY_ACTIONS, actions)]
> +
> +        mod = dp.ofproto_parser.OFPFlowMod(
> +            dp, cookie=0, cookie_mask=0, table_id=0,
> +            command=dp.ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
> +            priority=0xff, buffer_id=0xffffffff,
> +            out_port=dp.ofproto.OFPP_ANY, out_group=dp.ofproto.OFPG_ANY,
> +            flags=0, match=match, instructions=inst)
> +
> +        dp.send_msg(mod)
> +
> +    def _define_flow(self, dp):
> +        in_port = 1
> +        out_port = 2
> +
> +        eth_IP = ether.ETH_TYPE_IP
> +
> +        # ICMP -> DecNwTtl
> +        LOG.debug("--- add_flow DecNwTtl")
> +        match = dp.ofproto_parser.OFPMatch()
> +        match.set_in_port(in_port)
> +        match.set_dl_type(eth_IP)
> +        actions = [dp.ofproto_parser.OFPActionDecNwTtl(),
> +                   dp.ofproto_parser.OFPActionOutput(out_port, 0)]
> +        self._add_flow(dp, match, actions)
> +
> +    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
> +    def handler_datapath(self, ev):
> +        if ev.enter:
> +            self._define_flow(ev.dp)
> +
> +    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
> +    def packet_in_handler(self, ev):
> +        msg = ev.msg
> +        dst, src, eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 
> 0)
> +        in_port = msg.match.fields[0].value
> +
> +        LOG.info("----------------------------------------")
> +        LOG.info("* PacketIn")
> +        LOG.info("in_port=%d, eth_type: %s", in_port, hex(eth_type))
> +        LOG.info("packet reason=%d buffer_id=%d", msg.reason, msg.buffer_id)
> +        LOG.info("packet in datapath_id=%s src=%s dst=%s",
> +                 msg.datapath.id, haddr_to_str(src), haddr_to_str(dst))
> diff --git a/ryu/tests/mininet/packet_lib/arp/ARP_gratuitous.mn 
> b/ryu/tests/mininet/packet_lib/arp/ARP_gratuitous.mn
> new file mode 100644
> index 0000000..ca7a30a
> --- /dev/null
> +++ b/ryu/tests/mininet/packet_lib/arp/ARP_gratuitous.mn
> @@ -0,0 +1,7 @@
> +# test-GratuitousARP-request
> +TEST_NAME=GARP-Request
> +DUMP_HOST=h1
> +DUMP_IF=h1-eth0
> +RYU_APP=test_arp
> +PCAP_MZ="-S"
> +PCAP_FILTER="arp.isgratuitous && arp.src.proto_ipv4==10.0.0.100 && 
> arp.src.hw_mac==fe:ee:ee:ee:ee:ef"
> diff --git a/ryu/tests/mininet/packet_lib/arp/ARP_reply.mn 
> b/ryu/tests/mininet/packet_lib/arp/ARP_reply.mn
> new file mode 100644
> index 0000000..3969cba
> --- /dev/null
> +++ b/ryu/tests/mininet/packet_lib/arp/ARP_reply.mn
> @@ -0,0 +1,7 @@
> +# test-ARP-reply
> +TEST_NAME=ARP-Reply
> +DUMP_HOST=h1
> +DUMP_IF=h1-eth0
> +RYU_APP=test_arp
> +PCAP_MZ="-t arp request,targetip=10.0.0.100 -c 3 -r"
> +PCAP_FILTER="arp.opcode==reply && arp.src.proto_ipv4==10.0.0.100 && 
> arp.src.hw_mac==fe:ee:ee:ee:ee:ef"
> diff --git a/ryu/tests/mininet/packet_lib/arp/ARP_request.mn 
> b/ryu/tests/mininet/packet_lib/arp/ARP_request.mn
> new file mode 100644
> index 0000000..b44450e
> --- /dev/null
> +++ b/ryu/tests/mininet/packet_lib/arp/ARP_request.mn
> @@ -0,0 +1,7 @@
> +# test-ARP-request
> +TEST_NAME=ARP-Request
> +DUMP_HOST=h1
> +DUMP_IF=h1-eth0
> +RYU_APP=test_arp
> +PCAP_MZ="-t arp request,targetip=10.0.0.1"
> +PCAP_FILTER="arp.opcode==request && arp.src.proto_ipv4==10.0.0.100 && 
> arp.dst.proto_ipv4==10.0.0.1 && arp.src.hw_mac==fe:ee:ee:ee:ee:ef"
> diff --git a/ryu/tests/mininet/packet_lib/arp/test_arp.py 
> b/ryu/tests/mininet/packet_lib/arp/test_arp.py
> new file mode 100644
> index 0000000..39948f5
> --- /dev/null
> +++ b/ryu/tests/mininet/packet_lib/arp/test_arp.py
> @@ -0,0 +1,199 @@
> +# Copyright (C) 2012 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.
> +
> +# vim: tabstop=4 shiftwidth=4 softtabstop=4
> +
> +import logging
> +import array
> +import netaddr
> +
> +from ryu.base import app_manager
> +from ryu.controller import dpset
> +from ryu.controller import ofp_event
> +from ryu.controller import handler
> +from ryu.ofproto import ofproto_v1_2
> +from ryu.ofproto import ether
> +from ryu.ofproto import inet
> +from ryu.lib import mac
> +from ryu.lib.packet import packet
> +from ryu.lib.packet import ethernet
> +from ryu.lib.packet import arp
> +from ryu.lib.packet import ipv4
> +from ryu.lib.packet import icmp
> +
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class RunTestMininet(app_manager.RyuApp):
> +
> +    _CONTEXTS = {'dpset': dpset.DPSet}
> +    OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]
> +
> +    ZERO_MAC = mac.haddr_to_bin('00:00:00:00:00:00')
> +    BROADCAST_MAC = mac.haddr_to_bin('ff:ff:ff:ff:ff:ff')
> +    RYU_MAC = mac.haddr_to_bin('fe:ee:ee:ee:ee:ef')
> +    HOST_MAC = mac.haddr_to_bin('00:00:00:00:00:01')
> +    RYU_IP = int(netaddr.IPAddress('10.0.0.100'))
> +    HOST_IP = int(netaddr.IPAddress('10.0.0.1'))
> +
> +    def __init__(self, *args, **kwargs):
> +        super(RunTestMininet, self).__init__(*args, **kwargs)
> +
> +    def _send_msg(self, dp, data):
> +        buffer_id = 0xffffffff
> +        in_port = dp.ofproto.OFPP_LOCAL
> +        actions = [dp.ofproto_parser.OFPActionOutput(1, 0)]
> +        msg = dp.ofproto_parser.OFPPacketOut(
> +            dp, buffer_id, in_port, actions, data)
> +        dp.send_msg(msg)
> +
> +    def _add_flow(self, dp, match, actions):
> +        inst = [dp.ofproto_parser.OFPInstructionActions(
> +            dp.ofproto.OFPIT_APPLY_ACTIONS, actions)]
> +        mod = dp.ofproto_parser.OFPFlowMod(
> +            dp, cookie=0, cookie_mask=0, table_id=0,
> +            command=dp.ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
> +            priority=0xff, buffer_id=0xffffffff,
> +            out_port=dp.ofproto.OFPP_ANY, out_group=dp.ofproto.OFPG_ANY,
> +            flags=0, match=match, instructions=inst)
> +        dp.send_msg(mod)
> +
> +    def _find_protocol(self, pkt, name):
> +        for p in pkt.protocols:
> +            if hasattr(p, 'protocol_name'):
> +                if p.protocol_name == name:
> +                    return p
> +
> +    def _get_protocols(self, pkt):
> +        protocols = {}
> +        for p in pkt:
> +            if hasattr(p, 'protocol_name'):
> +                protocols[p.protocol_name] = p
> +            else:
> +                protocols['payload'] = p
> +        return protocols
> +
> +    def _build_ether(self, ethertype, dst_mac=HOST_MAC):
> +        e = ethernet.ethernet(dst_mac, self.RYU_MAC, ethertype)
> +        return e
> +
> +    def _build_arp(self, opcode, dst_ip=HOST_IP):
> +        if opcode == arp.ARP_REQUEST:
> +            _eth_dst_mac = self.BROADCAST_MAC
> +            _arp_dst_mac = self.ZERO_MAC
> +        elif opcode == arp.ARP_REPLY:
> +            _eth_dst_mac = self.HOST_MAC
> +            _arp_dst_mac = self.HOST_MAC
> +
> +        e = self._build_ether(ether.ETH_TYPE_ARP, _eth_dst_mac)
> +        a = arp.arp(hwtype=1, proto=ether.ETH_TYPE_IP, hlen=6, plen=4,
> +                    opcode=opcode, src_mac=self.RYU_MAC, src_ip=self.RYU_IP,
> +                    dst_mac=_arp_dst_mac, dst_ip=dst_ip)
> +        p = packet.Packet()
> +        p.add_protocol(e)
> +        p.add_protocol(a)
> +        p.serialize()
> +
> +        return p
> +
> +    def _build_echo(self, _type, echo):
> +        e = self._build_ether(ether.ETH_TYPE_IP)
> +        ip = ipv4.ipv4(version=4, header_length=5, tos=0, total_length=84,
> +                       identification=0, flags=0, offset=0, ttl=64,
> +                       proto=inet.IPPROTO_ICMP, csum=0,
> +                       src=self.RYU_IP, dst=self.HOST_IP)
> +        ping = icmp.icmp(_type, code=0, csum=0, data=echo)
> +
> +        p = packet.Packet()
> +        p.add_protocol(e)
> +        p.add_protocol(ip)
> +        p.add_protocol(ping)
> +        p.serialize()
> +        return p
> +
> +    def _garp(self):
> +        p = self._build_arp(arp.ARP_REQUEST, self.RYU_IP)
> +        return p.data
> +
> +    def _arp_request(self):
> +        p = self._build_arp(arp.ARP_REQUEST, self.HOST_IP)
> +        return p.data
> +
> +    def _arp_reply(self):
> +        p = self._build_arp(arp.ARP_REPLY, self.HOST_IP)
> +        return p.data
> +
> +    def _echo_request(self, echo):
> +        p = self._build_echo(icmp.ICMP_ECHO_REQUEST, echo)
> +        return p.data
> +
> +    def _echo_reply(self, echo):
> +        p = self._build_echo(icmp.ICMP_ECHO_REPLY, echo)
> +        return p.data
> +
> +    @handler.set_ev_cls(ofp_event.EventOFPPacketIn, handler.MAIN_DISPATCHER)
> +    def packet_in_handler(self, ev):
> +        msg = ev.msg
> +        dp = msg.datapath
> +
> +        pkt = packet.Packet(array.array('B', msg.data))
> +        p_arp = self._find_protocol(pkt, "arp")
> +        p_icmp = self._find_protocol(pkt, "icmp")
> +        p_ipv4 = self._find_protocol(pkt, "ipv4")
> +
> +        if p_arp:
> +            src_ip = str(netaddr.IPAddress(p_arp.src_ip))
> +            dst_ip = str(netaddr.IPAddress(p_arp.dst_ip))
> +            if p_arp.opcode == arp.ARP_REQUEST:
> +                LOG.debug("--- PacketIn: ARP_Request: %s->%s", src_ip, 
> dst_ip)
> +                if p_arp.dst_ip == self.RYU_IP:
> +                    LOG.debug("--- send Pkt: ARP_Reply")
> +                    data = self._arp_reply()
> +                    self._send_msg(dp, data)
> +                elif p_arp.dst_ip == self.HOST_IP:
> +                    LOG.debug("    PacketIn: GARP")
> +                    LOG.debug("--- send Pkt: ARP_Request")
> +                    data = self._arp_request()
> +                    self._send_msg(dp, data)
> +            elif p_arp.opcode == arp.ARP_REPLY:
> +                LOG.debug("--- PacketIn: ARP_Reply: %s->%s", src_ip, dst_ip)
> +                LOG.debug("--- send Pkt: Echo_Request")
> +                echo = icmp.echo(id_=66, seq=1)
> +                data = self._echo_request(echo)
> +                self._send_msg(dp, data)
> +
> +        if p_icmp:
> +            src = str(netaddr.IPAddress(p_ipv4.src))
> +            dst = str(netaddr.IPAddress(p_ipv4.dst))
> +            if p_icmp.type == icmp.ICMP_ECHO_REQUEST:
> +                LOG.debug("--- PacketIn: Echo_Request: %s->%s", src, dst)
> +                if p_ipv4.dst == self.RYU_IP:
> +                    LOG.debug("--- send Pkt: Echo_Reply")
> +                    echo = p_icmp.data
> +                    echo.data = bytearray(echo.data)
> +                    data = self._echo_reply(echo)
> +                    self._send_msg(dp, data)
> +            elif p_icmp.type == icmp.ICMP_ECHO_REPLY:
> +                LOG.debug("--- PacketIn: Echo_Reply: %s->%s", src, dst)
> +
> +    @handler.set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
> +    def handler_datapath(self, ev):
> +        if ev.enter:
> +            dp = ev.dp
> +
> +            LOG.debug("--- send Pkt: Gratuitous ARP_Request")
> +            data = self._garp()
> +            self._send_msg(dp, data)
> diff --git a/ryu/tests/mininet/run_mnet-test.sh 
> b/ryu/tests/mininet/run_mnet-test.sh
> new file mode 100755
> index 0000000..c1ecbe2
> --- /dev/null
> +++ b/ryu/tests/mininet/run_mnet-test.sh
> @@ -0,0 +1,274 @@
> +#!/bin/sh
> +
> +RUN_DIR=`dirname $0`
> +CMD_NAME=`basename $0 .sh`
> +CMD_PATH=`readlink -f $0`
> +CMD_DIR=`dirname $CMD_PATH`
> +DUMP_SEC=10
> +DUMP_DELAY=2
> +DUMP_DIR=/tmp/test-mn/dump
> +TEST_LIST=
> +TEST_SUFFIX=.mn
> +MN_PRE_FILE=/tmp/test-mn/mn-pre
> +MN_POST_FILE=/tmp/test-mn/mn-post
> +PKG_LIST="tshark tcpreplay mz"
> +RTN=0
> +
> +# usage
> +usage() {
> +    echo "Usage: $0 [OPTION] [TEST DIR or FILE]..."
> +    echo ""
> +    echo "Run Ryu's test in mininet"
> +    echo "ex.) $ $0 l2 l3/icmp/ICMP_ping.mn"
> +    echo ""
> +    echo "Options:"
> +    echo "  -h, --help  show this help message and exit"
> +    exit 0
> +}
> +
> +# set default environment
> +set_env() {
> +    POST_IF=h1-eth0
> +    DUMP_HOST=h2
> +    DUMP_IF=h2-eth0
> +    TEST_NAME=
> +    DUMP_FILE=
> +    RYU_APP=
> +    RYU_LOG=
> +    PCAP_MZ=
> +    PCAP_FILE=
> +    PCAP_FILTER=
> +    PCAP_COM=
> +    CACHE_HIT=
> +}
> +
> +# making mininet-test-pre-file
> +mn_pre() {
> +    exec 3>&1
> +    exec >$MN_PRE_FILE
> +    echo "sh echo '----------------------------------'"
> +    echo "sh echo '(pre) mininet topology dump.'"
> +    echo "sh echo '----------------------------------'"
> +    echo "dump"
> +    echo "net"
> +    echo "sh echo '----------------------------------'"
> +    echo "sh echo '(pre) tshark start.'"
> +    echo "sh echo '----------------------------------'"
> +    echo "$DUMP_HOST tshark -i $DUMP_IF -a duration:$DUMP_SEC -w $DUMP_FILE 
> &"
> +    echo "sh sleep $DUMP_DELAY"
> +    echo "sh echo '----------------------------------'"
> +    exec 1>&3
> +}
> +
> +# making mininet-test-post-file
> +mn_post() {
> +    exec 3>&1
> +    exec >$MN_POST_FILE
> +    echo "sh ovs-vsctl del-controller s1"
> +    echo "sh ovs-vsctl set bridge s1 protocols='[OpenFlow10,OpenFlow12]'"
> +    echo "sh ovs-vsctl set-controller s1 tcp:127.0.0.1"
> +    echo "sh echo '----------------------------------'"
> +    echo "sh echo '(post) packet sending...'"
> +    echo "sh echo '----------------------------------'"
> +    echo $PCAP_COM
> +    echo "sh sleep 1"
> +    echo "sh echo '----------------------------------'"
> +    echo "sh echo '(post) dump flows.'"
> +    echo "sh echo '----------------------------------'"
> +    echo "sh ovs-ofctl dump-flows s1"
> +    echo "sh echo '----------------------------------'"
> +    exec 1>&3
> +}
> +
> +# ovs cache-hit incremental check
> +ovs_cache_hit() {
> +    expr `sudo ovs-dpctl show|sed -n 's|lookups: hit:||gp'|awk '{print $1}'` 
> - ${1:-0}
> +}
> +
> +# starting ryu-manager
> +run_ryu() {
> +    ERRSTAT=0
> +    ERRTAG="run_ryu() :"
> +
> +    echo "Inf: RYU_APP=$RYU_APP"
> +    echo "Inf: ryu-manager starting..."
> +    ryu-manager --verbose $RYU_APP 2>$DUMP_DIR/$RYU_LOG &
> +    PID_RYU=$!
> +    sleep 1
> +    [ -d /proc/$PID_RYU ] || err $ERRTAG "failed to start ryu-manager."
> +
> +    return $ERRSTAT
> +}
> +
> +# starting mininet and test-script
> +run_mn() {
> +    echo "Info: mininet starting..."
> +    sudo mn --mac --test none --pre $MN_PRE_FILE --post $MN_POST_FILE \
> +            --controller remote 127.0.0.1
> +}
> +
> +# cleaning after mininet
> +clean_mn() {
> +    wait_ryu
> +    rm -f $MN_PRE_FILE $MN_POST_FILE
> +}
> +
> +# check packet and chache-hit
> +check() {
> +    PACKET=`tshark -r $DUMP_FILE -R "$PCAP_FILTER" 2>/dev/null`
> +    if [ ! "$PACKET" ]; then
> +        RESULT=NG
> +        REASON="(unmatched packet. please check $DUMP_FILE)"
> +    elif [ "$CACHE_HIT" ] && [ `ovs_cache_hit $CACHE_HIT` -eq 0 ]; then
> +        RESULT=NG
> +        REASON="(ovs cache hit miss.)"
> +    else
> +        RESULT=OK; REASON=
> +    fi
> +    echo
> +    echo "TEST ${TEST_NAME} : $RESULT $REASON"
> +}
> +
> +# stoping ryu-manager
> +wait_ryu() {
> +    kill -2 $PID_RYU
> +    wait $PID_RYU
> +}
> +
> +# test-main
> +test_mn() {
> +    DUMP_FILE=$DUMP_DIR/$DUMP_FILE
> +    touch $DUMP_FILE
> +    sudo chmod o+w $DUMP_FILE
> +    [ "$CACHE_HIT" ] && CACHE_HIT=`ovs_cache_hit 0`
> +    mn_pre
> +    mn_post
> +    run_ryu; [ $? -ne 0 ] && return 1
> +    run_mn; [ $? -ne 0 ] && return 1
> +    check
> +
> +    return 0
> +}
> +
> +err() {
> +    echo Error: $*
> +    ERRSTAT=1
> +}
> +
> +mnfile_check() {
> +    test=`basename $1 $TEST_SUFFIX`
> +    file=`readlink -f $1`
> +    TEST_DIR=`dirname $file`
> +    ERRSTAT=0
> +    ERRTAG="mnfile_check() :"
> +
> +    # test-file check
> +    if [ ! -r $file ]; then
> +        err $ERRTAG "cannot open the file: $file"
> +        return $ERRSTAT
> +    fi
> +
> +    . $file || err $ERRTAG "failed to include $file"
> +
> +    # parameter check
> +    [ "$RYU_APP" ] || err $ERRTAG: "RYU_APP is not defined"
> +    [ "$PCAP_FILE" -o "$PCAP_MZ" ] || err $ERRTAG: "PCAP_FILE or PCAP_MZ is 
> not defined"
> +    [ "$PCAP_FILTER" ] || err $ERRTAG "PCAP_FILTER is not defined"
> +    [ "$TEST_NAME" ] || TEST_NAME=$test
> +    [ "$DUMP_FILE" ] || DUMP_FILE=$test.dump
> +    [ "$RYU_LOG" ] || RYU_LOG=ryu-manager.$test.log
> +    [ $ERRSTAT -ne 0 ] && return $ERRSTAT
> +
> +    # pcap check (pcap-file or mz-option)
> +    if [ "$PCAP_FILE" ]; then
> +        PCAP_FILE=$TEST_DIR/$PCAP_FILE
> +        [ -r $PCAP_FILE ] || err $ERRTAG "PCAP_FILE[$PCAP_FILE] cannot read"
> +        PCAP_COM="h1 tcpreplay -l 3 -i $POST_IF $PCAP_FILE"
> +    elif [ "$PCAP_MZ" ]; then
> +        PCAP_COM="h1 mz $POST_IF $PCAP_MZ"
> +    fi
> +    [ $ERRSTAT -ne 0 ] && return $ERRSTAT
> +
> +    # ryu-app check
> +    [ -r $TEST_DIR/$RYU_APP -o -r $TEST_DIR/${RYU_APP}.py ] && 
> RYU_APP=$TEST_DIR/$RYU_APP
> +
> +    return $ERRSTAT
> +}
> +
> +arg_check() {
> +    ARGLIST=
> +    ERRTAG="argcheck() :"
> +
> +    case "$1" in
> +        -h|--help) usage;;
> +    esac
> +
> +    if [ $# -ne 0 ]; then
> +        ARGLIST=$*
> +    else
> +     ARGLIST=`find . -type f -name "*$TEST_SUFFIX"`
> +    fi
> +
> +    for arg in $ARGLIST; do
> +        if [ -d $arg ]; then
> +            file=`find $arg -type f -name "*$TEST_SUFFIX"`
> +        elif [ -f $arg ]; then
> +            file=$arg
> +        else
> +            err $ERRTAG "$arg is not found"
> +            file=
> +        fi
> +
> +        TEST_LIST="$TEST_LIST $file"
> +    done
> +}
> +
> +pkg_check() {
> +    no_pkg=
> +    for pkg in $PKG_LIST; do
> +        [ ! `which $pkg` ] && no_pkg="$no_pkg $pkg"
> +    done
> +    for pkg in $no_pkg; do
> +        echo "Error: Package [ $pkg ] is not found. Please install."
> +    done
> +    [ "$no_pkg" ] && exit 1
> +}
> +
> +### main
> +[ -d $DUMP_DIR ] || mkdir -p $DUMP_DIR
> +
> +pkg_check
> +arg_check $*
> +echo "\n---------- test target ----------"
> +for testfile in $TEST_LIST; do echo $testfile; done
> +
> +count=0
> +for testfile in $TEST_LIST; do
> +    echo "\n---------- test [$testfile] start ----------"
> +    set_env
> +    mnfile_check $testfile && test_mn
> +    case $? in
> +        0) msg="finished : $RESULT" ;;
> +        *) msg="skipped with error"; RESULT="skip" ;;
> +    esac
> +    eval RESULT_${count}=\$RESULT
> +    eval REASON_${count}=\$REASON
> +    count=`expr $count + 1`
> +    num=`eval echo \\${num_$RESULT:-0}`
> +    eval num_${RESULT}=`expr $num + 1`
> +    [ "$RESULT" != "OK" ] && RTN=1
> +    clean_mn
> +    echo "\n---------- test [$testfile] $msg ----------"
> +done
> +
> +# output summary results
> +echo "\n---------- test results ----------"
> +count=0
> +for testfile in $TEST_LIST; do
> +    eval echo \$testfile : \$RESULT_${count} \$REASON_${count}
> +    count=`expr $count + 1`
> +done
> +echo "----------------------------------"
> +echo "Ran $count tests. Result: ${num_OK:+OK=}$num_OK ${num_NG:+NG=}$num_NG 
> ${num_skip:+skip=}$num_skip"
> +
> +exit $RTN
> -- 
> 1.7.9.5
> 
> 
> 
> ------------------------------------------------------------------------------
> Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
> MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
> with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
> MVPs and experts. ON SALE this month only -- learn more at:
> http://p.sf.net/sfu/learnnow-d2d
> _______________________________________________
> Ryu-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ryu-devel

---------------------------------------
NTTソフトウェア株式会社
技術開発センター OSS基盤技術部門

 檜山 学 (Hiyama Manabu)

TEL: 045-212-7393 FAX: 045-662-7856
---------------------------------------



------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnnow-d2d
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to