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
