summaryrefslogtreecommitdiffhomepage
path: root/tests/mininet
diff options
context:
space:
mode:
Diffstat (limited to 'tests/mininet')
-rw-r--r--tests/mininet/l2/mpls/PopMPLS_mpls.mn6
-rw-r--r--tests/mininet/l2/mpls/PushMPLS_ip.mn6
-rw-r--r--tests/mininet/l2/mpls/PushMPLS_mpls.mn6
-rw-r--r--tests/mininet/l2/mpls/test_mpls.py127
-rw-r--r--tests/mininet/l2/vlan/PopVLAN_vlan.mn6
-rw-r--r--tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn6
-rw-r--r--tests/mininet/l2/vlan/PushVLAN_icmp.mn6
-rw-r--r--tests/mininet/l2/vlan/test_vlan.py130
-rw-r--r--tests/mininet/l3/icmp/ICMP_ping.mn6
-rw-r--r--tests/mininet/l3/icmp/ICMP_reply.mn6
-rw-r--r--tests/mininet/l3/icmp/test_icmp.py84
-rw-r--r--tests/mininet/l3/ip_ttl/DecNwTtl.mn6
-rw-r--r--tests/mininet/l3/ip_ttl/test_ip_ttl.py84
-rw-r--r--tests/mininet/packet_lib/arp/ARP_gratuitous.mn7
-rw-r--r--tests/mininet/packet_lib/arp/ARP_reply.mn7
-rw-r--r--tests/mininet/packet_lib/arp/ARP_request.mn7
-rw-r--r--tests/mininet/packet_lib/arp/test_arp.py199
-rwxr-xr-xtests/mininet/run_mnet-test.sh274
18 files changed, 973 insertions, 0 deletions
diff --git a/tests/mininet/l2/mpls/PopMPLS_mpls.mn b/tests/mininet/l2/mpls/PopMPLS_mpls.mn
new file mode 100644
index 00000000..45fa9f96
--- /dev/null
+++ b/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/tests/mininet/l2/mpls/PushMPLS_ip.mn b/tests/mininet/l2/mpls/PushMPLS_ip.mn
new file mode 100644
index 00000000..2634e788
--- /dev/null
+++ b/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/tests/mininet/l2/mpls/PushMPLS_mpls.mn b/tests/mininet/l2/mpls/PushMPLS_mpls.mn
new file mode 100644
index 00000000..5ac1702f
--- /dev/null
+++ b/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/tests/mininet/l2/mpls/test_mpls.py b/tests/mininet/l2/mpls/test_mpls.py
new file mode 100644
index 00000000..3090a08c
--- /dev/null
+++ b/tests/mininet/l2/mpls/test_mpls.py
@@ -0,0 +1,127 @@
+# 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)
+
+ 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/tests/mininet/l2/vlan/PopVLAN_vlan.mn b/tests/mininet/l2/vlan/PopVLAN_vlan.mn
new file mode 100644
index 00000000..f1d1c6dd
--- /dev/null
+++ b/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/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn b/tests/mininet/l2/vlan/PopVLAN_vlanvlan.mn
new file mode 100644
index 00000000..90444a75
--- /dev/null
+++ b/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/tests/mininet/l2/vlan/PushVLAN_icmp.mn b/tests/mininet/l2/vlan/PushVLAN_icmp.mn
new file mode 100644
index 00000000..439ad233
--- /dev/null
+++ b/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/tests/mininet/l2/vlan/test_vlan.py b/tests/mininet/l2/vlan/test_vlan.py
new file mode 100644
index 00000000..0b1be7fc
--- /dev/null
+++ b/tests/mininet/l2/vlan/test_vlan.py
@@ -0,0 +1,130 @@
+# 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)
+
+ 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/tests/mininet/l3/icmp/ICMP_ping.mn b/tests/mininet/l3/icmp/ICMP_ping.mn
new file mode 100644
index 00000000..f558693d
--- /dev/null
+++ b/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/tests/mininet/l3/icmp/ICMP_reply.mn b/tests/mininet/l3/icmp/ICMP_reply.mn
new file mode 100644
index 00000000..eb6bc8b6
--- /dev/null
+++ b/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/tests/mininet/l3/icmp/test_icmp.py b/tests/mininet/l3/icmp/test_icmp.py
new file mode 100644
index 00000000..090f83e5
--- /dev/null
+++ b/tests/mininet/l3/icmp/test_icmp.py
@@ -0,0 +1,84 @@
+# 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)
+
+ 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/tests/mininet/l3/ip_ttl/DecNwTtl.mn b/tests/mininet/l3/ip_ttl/DecNwTtl.mn
new file mode 100644
index 00000000..60cd4623
--- /dev/null
+++ b/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/tests/mininet/l3/ip_ttl/test_ip_ttl.py b/tests/mininet/l3/ip_ttl/test_ip_ttl.py
new file mode 100644
index 00000000..f6f00ab9
--- /dev/null
+++ b/tests/mininet/l3/ip_ttl/test_ip_ttl.py
@@ -0,0 +1,84 @@
+# 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)
+
+ 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/tests/mininet/packet_lib/arp/ARP_gratuitous.mn b/tests/mininet/packet_lib/arp/ARP_gratuitous.mn
new file mode 100644
index 00000000..ca7a30ae
--- /dev/null
+++ b/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/tests/mininet/packet_lib/arp/ARP_reply.mn b/tests/mininet/packet_lib/arp/ARP_reply.mn
new file mode 100644
index 00000000..3969cba1
--- /dev/null
+++ b/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/tests/mininet/packet_lib/arp/ARP_request.mn b/tests/mininet/packet_lib/arp/ARP_request.mn
new file mode 100644
index 00000000..b44450ef
--- /dev/null
+++ b/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/tests/mininet/packet_lib/arp/test_arp.py b/tests/mininet/packet_lib/arp/test_arp.py
new file mode 100644
index 00000000..39948f54
--- /dev/null
+++ b/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/tests/mininet/run_mnet-test.sh b/tests/mininet/run_mnet-test.sh
new file mode 100755
index 00000000..c1ecbe23
--- /dev/null
+++ b/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