summaryrefslogtreecommitdiffhomepage
path: root/tests/unit/packet
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-06-26 15:04:43 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-06-26 15:17:44 +0900
commita67ed2858417b9d795460f05126c01fb0cd344f9 (patch)
tree8171336c30668f8fce7d18125a591de86c322f40 /tests/unit/packet
parentd8ae9491dab0824eb88b7e8aad044302d1463f84 (diff)
tests: Separate test files from Ryu module
To prevent redundant files (e.g., pcap files, json files for tests, packet data generator) to be installed, this patch separates test directory from Ryu module. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'tests/unit/packet')
-rw-r--r--tests/unit/packet/__init__.py0
-rw-r--r--tests/unit/packet/test_arp.py183
-rw-r--r--tests/unit/packet/test_bfd.py320
-rw-r--r--tests/unit/packet/test_bgp.py813
-rw-r--r--tests/unit/packet/test_bmp.py136
-rw-r--r--tests/unit/packet/test_bpdu.py469
-rw-r--r--tests/unit/packet/test_cfm.py1761
-rw-r--r--tests/unit/packet/test_dhcp.py218
-rw-r--r--tests/unit/packet/test_ethernet.py103
-rw-r--r--tests/unit/packet/test_geneve.py62
-rw-r--r--tests/unit/packet/test_gre.py115
-rw-r--r--tests/unit/packet/test_icmp.py380
-rw-r--r--tests/unit/packet/test_icmpv6.py2039
-rw-r--r--tests/unit/packet/test_igmp.py997
-rw-r--r--tests/unit/packet/test_ipv4.py137
-rw-r--r--tests/unit/packet/test_ipv6.py1128
-rw-r--r--tests/unit/packet/test_llc.py42
-rw-r--r--tests/unit/packet/test_lldp.py533
-rw-r--r--tests/unit/packet/test_mpls.py92
-rw-r--r--tests/unit/packet/test_openflow.py64
-rw-r--r--tests/unit/packet/test_ospf.py120
-rw-r--r--tests/unit/packet/test_packet.py1553
-rw-r--r--tests/unit/packet/test_pbb.py172
-rw-r--r--tests/unit/packet/test_sctp.py1454
-rw-r--r--tests/unit/packet/test_slow.py1104
-rw-r--r--tests/unit/packet/test_tcp.py267
-rw-r--r--tests/unit/packet/test_udp.py110
-rw-r--r--tests/unit/packet/test_vlan.py265
-rw-r--r--tests/unit/packet/test_vrrp.py496
-rw-r--r--tests/unit/packet/test_vxlan.py82
-rw-r--r--tests/unit/packet/test_zebra.py66
31 files changed, 15281 insertions, 0 deletions
diff --git a/tests/unit/packet/__init__.py b/tests/unit/packet/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/unit/packet/__init__.py
diff --git a/tests/unit/packet/test_arp.py b/tests/unit/packet/test_arp.py
new file mode 100644
index 00000000..40e28131
--- /dev/null
+++ b/tests/unit/packet/test_arp.py
@@ -0,0 +1,183 @@
+# 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 unittest
+import logging
+import struct
+from struct import *
+from nose.tools import *
+from ryu.ofproto import ether
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet.arp import arp
+from ryu.lib.packet.vlan import vlan
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger('test_arp')
+
+
+class Test_arp(unittest.TestCase):
+ """ Test case for arp
+ """
+
+ hwtype = 1
+ proto = 0x0800
+ hlen = 6
+ plen = 4
+ opcode = 1
+ src_mac = '00:07:0d:af:f4:54'
+ src_ip = '24.166.172.1'
+ dst_mac = '00:00:00:00:00:00'
+ dst_ip = '24.166.173.159'
+
+ fmt = arp._PACK_STR
+ buf = pack(fmt, hwtype, proto, hlen, plen, opcode,
+ addrconv.mac.text_to_bin(src_mac),
+ addrconv.ipv4.text_to_bin(src_ip),
+ addrconv.mac.text_to_bin(dst_mac),
+ addrconv.ipv4.text_to_bin(dst_ip))
+
+ a = arp(hwtype, proto, hlen, plen, opcode, src_mac, src_ip, dst_mac,
+ dst_ip)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.hwtype, self.a.hwtype)
+ eq_(self.proto, self.a.proto)
+ eq_(self.hlen, self.a.hlen)
+ eq_(self.plen, self.a.plen)
+ eq_(self.opcode, self.a.opcode)
+ eq_(self.src_mac, self.a.src_mac)
+ eq_(self.src_ip, self.a.src_ip)
+ eq_(self.dst_mac, self.a.dst_mac)
+ eq_(self.dst_ip, self.a.dst_ip)
+
+ def test_parser(self):
+ _res = self.a.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res.hwtype, self.hwtype)
+ eq_(res.proto, self.proto)
+ eq_(res.hlen, self.hlen)
+ eq_(res.plen, self.plen)
+ eq_(res.opcode, self.opcode)
+ eq_(res.src_mac, self.src_mac)
+ eq_(res.src_ip, self.src_ip)
+ eq_(res.dst_mac, self.dst_mac)
+ eq_(res.dst_ip, self.dst_ip)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.a.serialize(data, prev)
+
+ fmt = arp._PACK_STR
+ res = struct.unpack(fmt, buf)
+
+ eq_(res[0], self.hwtype)
+ eq_(res[1], self.proto)
+ eq_(res[2], self.hlen)
+ eq_(res[3], self.plen)
+ eq_(res[4], self.opcode)
+ eq_(res[5], addrconv.mac.text_to_bin(self.src_mac))
+ eq_(res[6], addrconv.ipv4.text_to_bin(self.src_ip))
+ eq_(res[7], addrconv.mac.text_to_bin(self.dst_mac))
+ eq_(res[8], addrconv.ipv4.text_to_bin(self.dst_ip))
+
+ def _build_arp(self, vlan_enabled):
+ if vlan_enabled is True:
+ ethertype = ether.ETH_TYPE_8021Q
+ v = vlan(1, 1, 3, ether.ETH_TYPE_ARP)
+ else:
+ ethertype = ether.ETH_TYPE_ARP
+ e = ethernet(self.dst_mac, self.src_mac, ethertype)
+ p = Packet()
+
+ p.add_protocol(e)
+ if vlan_enabled is True:
+ p.add_protocol(v)
+ p.add_protocol(self.a)
+ p.serialize()
+ return p
+
+ def test_build_arp_vlan(self):
+ p = self._build_arp(True)
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_8021Q)
+
+ v = self.find_protocol(p, "vlan")
+ ok_(v)
+ eq_(v.ethertype, ether.ETH_TYPE_ARP)
+
+ a = self.find_protocol(p, "arp")
+ ok_(a)
+
+ eq_(a.hwtype, self.hwtype)
+ eq_(a.proto, self.proto)
+ eq_(a.hlen, self.hlen)
+ eq_(a.plen, self.plen)
+ eq_(a.opcode, self.opcode)
+ eq_(a.src_mac, self.src_mac)
+ eq_(a.src_ip, self.src_ip)
+ eq_(a.dst_mac, self.dst_mac)
+ eq_(a.dst_ip, self.dst_ip)
+
+ def test_build_arp_novlan(self):
+ p = self._build_arp(False)
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_ARP)
+
+ a = self.find_protocol(p, "arp")
+ ok_(a)
+
+ eq_(a.hwtype, self.hwtype)
+ eq_(a.proto, self.proto)
+ eq_(a.hlen, self.hlen)
+ eq_(a.plen, self.plen)
+ eq_(a.opcode, self.opcode)
+ eq_(a.src_mac, self.src_mac)
+ eq_(a.src_ip, self.src_ip)
+ eq_(a.dst_mac, self.dst_mac)
+ eq_(a.dst_ip, self.dst_ip)
+
+ @raises(Exception)
+ def test_malformed_arp(self):
+ m_short_buf = self.buf[1:arp._MIN_LEN]
+ arp.parser(m_short_buf)
+
+ def test_json(self):
+ jsondict = self.a.to_jsondict()
+ a = arp.from_jsondict(jsondict['arp'])
+ eq_(str(self.a), str(a))
diff --git a/tests/unit/packet/test_bfd.py b/tests/unit/packet/test_bfd.py
new file mode 100644
index 00000000..d33949cc
--- /dev/null
+++ b/tests/unit/packet/test_bfd.py
@@ -0,0 +1,320 @@
+# Copyright (C) 2014 Xinguard, Inc.
+#
+# 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 unittest
+import logging
+import struct
+import inspect
+from nose.tools import ok_, eq_, nottest
+
+from ryu.ofproto import ether
+from ryu.ofproto import inet
+from ryu.lib.packet import packet
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import ipv4
+from ryu.lib.packet import udp
+from ryu.lib.packet import bfd
+from ryu.lib import addrconv
+
+LOG = logging.getLogger(__name__)
+
+
+class TestBFD(unittest.TestCase):
+ def setUp(self):
+ # BFD packet without authentication.
+ self.data = b'\xb0\xa8\x6e\x18\xb8\x08\x64\x87' \
+ + b'\x88\xe9\xcb\xc8\x08\x00\x45\xc0' \
+ + b'\x00\x34\x68\x49\x00\x00\xff\x11' \
+ + b'\xf4\x73\xac\x1c\x03\x01\xac\x1c' \
+ + b'\x03\x02\xc0\x00\x0e\xc8\x00\x20' \
+ + b'\xd9\x02\x21\xc0\x03\x18\x00\x00' \
+ + b'\x00\x06\x00\x00\x00\x07\x00\x00' \
+ + b'\xea\x60\x00\x00\xea\x60\x00\x00' \
+ + b'\x00\x00'
+
+ # BFD packet using simple password authentication.
+ self.data_auth_simple = b'\x08\x00\x27\xd1\x95\x7c\x08\x00' \
+ + b'\x27\xed\x54\x41\x08\x00\x45\xc0' \
+ + b'\x00\x3d\x0c\x90\x00\x00\xff\x11' \
+ + b'\xbb\x0b\xc0\xa8\x39\x02\xc0\xa8' \
+ + b'\x39\x01\xc0\x00\x0e\xc8\x00\x29' \
+ + b'\x46\x35\x20\x44\x03\x21\x00\x00' \
+ + b'\x00\x01\x00\x00\x00\x00\x00\x0f' \
+ + b'\x42\x40\x00\x0f\x42\x40\x00\x00' \
+ + b'\x00\x00\x01\x09\x02\x73\x65\x63' \
+ + b'\x72\x65\x74'
+
+ # BFD packet using md5 authentication.
+ self.data_auth_md5 = b'\x08\x00\x27\xd1\x95\x7c\x08\x00' \
+ + b'\x27\xed\x54\x41\x08\x00\x45\xc0' \
+ + b'\x00\x4c\x0c\x44\x00\x00\xff\x11' \
+ + b'\xbb\x48\xc0\xa8\x39\x02\xc0\xa8' \
+ + b'\x39\x01\xc0\x00\x0e\xc8\x00\x38' \
+ + b'\x51\xbc\x20\x44\x03\x30\x00\x00' \
+ + b'\x00\x01\x00\x00\x00\x00\x00\x0f' \
+ + b'\x42\x40\x00\x0f\x42\x40\x00\x00' \
+ + b'\x00\x00\x02\x18\x02\x00\x00\x00' \
+ + b'\x41\xdb\x66\xa8\xf9\x25\x5a\x8b' \
+ + b'\xcb\x7e\x4b\xec\x25\xa6\x2c\x23' \
+ + b'\xda\x0f'
+
+ # BFD packet using SHA1 authentication.
+ self.data_auth_sha1 = b'\x08\x00\x27\xd1\x95\x7c\x08\x00' \
+ + b'\x27\xed\x54\x41\x08\x00\x45\xc0' \
+ + b'\x00\x50\x0b\x90\x00\x00\xff\x11' \
+ + b'\xbb\xf8\xc0\xa8\x39\x02\xc0\xa8' \
+ + b'\x39\x01\xc0\x00\x0e\xc8\x00\x3c' \
+ + b'\xb9\x92\x20\x44\x03\x34\x00\x00' \
+ + b'\x00\x01\x00\x00\x00\x00\x00\x0f' \
+ + b'\x42\x40\x00\x0f\x42\x40\x00\x00' \
+ + b'\x00\x00\x04\x1c\x02\x00\x00\x00' \
+ + b'\x41\xb1\x46\x20\x10\x81\x03\xd7' \
+ + b'\xf4\xde\x87\x61\x4c\x24\x61\x1f' \
+ + b'\x3c\xc1\x6a\x00\x69\x23'
+
+ # BFD Key chain {auth_key_id: auth_key/password}
+ self.auth_keys = {2: b"secret"}
+
+ def tearDown(self):
+ pass
+
+ def test_parse(self):
+ buf = self.data
+ pkt = packet.Packet(buf)
+ i = iter(pkt)
+
+ eq_(type(next(i)), ethernet.ethernet)
+ eq_(type(next(i)), ipv4.ipv4)
+ eq_(type(next(i)), udp.udp)
+ eq_(type(bfd.bfd.parser(next(i))[0]), bfd.bfd)
+
+ def test_parse_with_auth_simple(self):
+ buf = self.data_auth_simple
+ pkt = packet.Packet(buf)
+ i = iter(pkt)
+
+ eq_(type(next(i)), ethernet.ethernet)
+ eq_(type(next(i)), ipv4.ipv4)
+ eq_(type(next(i)), udp.udp)
+
+ bfd_obj = bfd.bfd.parser(next(i))[0]
+ eq_(type(bfd_obj), bfd.bfd)
+ eq_(type(bfd_obj.auth_cls), bfd.SimplePassword)
+ ok_(bfd_obj.authenticate(self.auth_keys))
+
+ def test_parse_with_auth_md5(self):
+ buf = self.data_auth_md5
+ pkt = packet.Packet(buf)
+ i = iter(pkt)
+
+ eq_(type(next(i)), ethernet.ethernet)
+ eq_(type(next(i)), ipv4.ipv4)
+ eq_(type(next(i)), udp.udp)
+
+ bfd_obj = bfd.bfd.parser(next(i))[0]
+ eq_(type(bfd_obj), bfd.bfd)
+ eq_(type(bfd_obj.auth_cls), bfd.KeyedMD5)
+ ok_(bfd_obj.authenticate(self.auth_keys))
+
+ def test_parse_with_auth_sha1(self):
+ buf = self.data_auth_sha1
+ pkt = packet.Packet(buf)
+ i = iter(pkt)
+
+ eq_(type(next(i)), ethernet.ethernet)
+ eq_(type(next(i)), ipv4.ipv4)
+ eq_(type(next(i)), udp.udp)
+
+ bfd_obj = bfd.bfd.parser(next(i))[0]
+ eq_(type(bfd_obj), bfd.bfd)
+ eq_(type(bfd_obj.auth_cls), bfd.KeyedSHA1)
+ ok_(bfd_obj.authenticate(self.auth_keys))
+
+ def test_serialize(self):
+ pkt = packet.Packet()
+
+ eth_pkt = ethernet.ethernet('b0:a8:6e:18:b8:08', '64:87:88:e9:cb:c8')
+ pkt.add_protocol(eth_pkt)
+
+ ip_pkt = ipv4.ipv4(src='172.28.3.1', dst='172.28.3.2', tos=192,
+ identification=26697, proto=inet.IPPROTO_UDP)
+ pkt.add_protocol(ip_pkt)
+
+ udp_pkt = udp.udp(49152, 3784)
+ pkt.add_protocol(udp_pkt)
+
+ bfd_pkt = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_CTRL_DETECT_TIME_EXPIRED,
+ state=bfd.BFD_STATE_UP, detect_mult=3, my_discr=6,
+ your_discr=7, desired_min_tx_interval=60000,
+ required_min_rx_interval=60000,
+ required_min_echo_rx_interval=0)
+ pkt.add_protocol(bfd_pkt)
+
+ eq_(len(pkt.protocols), 4)
+
+ pkt.serialize()
+ eq_(pkt.data, self.data)
+
+ def test_serialize_with_auth_simple(self):
+ pkt = packet.Packet()
+
+ eth_pkt = ethernet.ethernet('08:00:27:d1:95:7c', '08:00:27:ed:54:41')
+ pkt.add_protocol(eth_pkt)
+
+ ip_pkt = ipv4.ipv4(src='192.168.57.2', dst='192.168.57.1', tos=192,
+ identification=3216, proto=inet.IPPROTO_UDP)
+ pkt.add_protocol(ip_pkt)
+
+ udp_pkt = udp.udp(49152, 3784)
+ pkt.add_protocol(udp_pkt)
+
+ auth_cls = bfd.SimplePassword(auth_key_id=2,
+ password=self.auth_keys[2])
+
+ bfd_pkt = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_NO_DIAG,
+ flags=bfd.BFD_FLAG_AUTH_PRESENT,
+ state=bfd.BFD_STATE_DOWN, detect_mult=3, my_discr=1,
+ your_discr=0, desired_min_tx_interval=1000000,
+ required_min_rx_interval=1000000,
+ required_min_echo_rx_interval=0,
+ auth_cls=auth_cls)
+
+ pkt.add_protocol(bfd_pkt)
+
+ eq_(len(pkt.protocols), 4)
+
+ pkt.serialize()
+ eq_(pkt.data, self.data_auth_simple)
+
+ def test_serialize_with_auth_md5(self):
+ pkt = packet.Packet()
+
+ eth_pkt = ethernet.ethernet('08:00:27:d1:95:7c', '08:00:27:ed:54:41')
+ pkt.add_protocol(eth_pkt)
+
+ ip_pkt = ipv4.ipv4(src='192.168.57.2', dst='192.168.57.1', tos=192,
+ identification=3140, proto=inet.IPPROTO_UDP)
+ pkt.add_protocol(ip_pkt)
+
+ udp_pkt = udp.udp(49152, 3784)
+ pkt.add_protocol(udp_pkt)
+
+ auth_cls = bfd.KeyedMD5(auth_key_id=2, seq=16859,
+ auth_key=self.auth_keys[2])
+
+ bfd_pkt = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_NO_DIAG,
+ flags=bfd.BFD_FLAG_AUTH_PRESENT,
+ state=bfd.BFD_STATE_DOWN, detect_mult=3, my_discr=1,
+ your_discr=0, desired_min_tx_interval=1000000,
+ required_min_rx_interval=1000000,
+ required_min_echo_rx_interval=0,
+ auth_cls=auth_cls)
+
+ pkt.add_protocol(bfd_pkt)
+
+ eq_(len(pkt.protocols), 4)
+
+ pkt.serialize()
+ eq_(pkt.data, self.data_auth_md5)
+
+ def test_serialize_with_auth_sha1(self):
+ pkt = packet.Packet()
+
+ eth_pkt = ethernet.ethernet('08:00:27:d1:95:7c', '08:00:27:ed:54:41')
+ pkt.add_protocol(eth_pkt)
+
+ ip_pkt = ipv4.ipv4(src='192.168.57.2', dst='192.168.57.1', tos=192,
+ identification=2960, proto=inet.IPPROTO_UDP)
+ pkt.add_protocol(ip_pkt)
+
+ udp_pkt = udp.udp(49152, 3784)
+ pkt.add_protocol(udp_pkt)
+
+ auth_cls = bfd.KeyedSHA1(auth_key_id=2, seq=16817,
+ auth_key=self.auth_keys[2])
+
+ bfd_pkt = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_NO_DIAG,
+ flags=bfd.BFD_FLAG_AUTH_PRESENT,
+ state=bfd.BFD_STATE_DOWN, detect_mult=3, my_discr=1,
+ your_discr=0, desired_min_tx_interval=1000000,
+ required_min_rx_interval=1000000,
+ required_min_echo_rx_interval=0,
+ auth_cls=auth_cls)
+
+ pkt.add_protocol(bfd_pkt)
+
+ eq_(len(pkt.protocols), 4)
+
+ pkt.serialize()
+ eq_(pkt.data, self.data_auth_sha1)
+
+ def test_json(self):
+ bfd1 = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_CTRL_DETECT_TIME_EXPIRED,
+ state=bfd.BFD_STATE_UP, detect_mult=3, my_discr=6,
+ your_discr=7, desired_min_tx_interval=60000,
+ required_min_rx_interval=60000,
+ required_min_echo_rx_interval=0)
+
+ jsondict = bfd1.to_jsondict()
+ bfd2 = bfd.bfd.from_jsondict(jsondict['bfd'])
+ eq_(str(bfd1), str(bfd2))
+
+ def test_json_with_auth_simple(self):
+ auth_cls = bfd.SimplePassword(auth_key_id=2,
+ password=self.auth_keys[2])
+
+ bfd1 = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_NO_DIAG,
+ flags=bfd.BFD_FLAG_AUTH_PRESENT,
+ state=bfd.BFD_STATE_DOWN, detect_mult=3, my_discr=1,
+ your_discr=0, desired_min_tx_interval=1000000,
+ required_min_rx_interval=1000000,
+ required_min_echo_rx_interval=0,
+ auth_cls=auth_cls)
+
+ jsondict = bfd1.to_jsondict()
+ bfd2 = bfd.bfd.from_jsondict(jsondict['bfd'])
+ eq_(str(bfd1), str(bfd2))
+
+ def test_json_with_auth_md5(self):
+ auth_cls = bfd.KeyedMD5(auth_key_id=2, seq=16859,
+ auth_key=self.auth_keys[2])
+
+ bfd1 = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_NO_DIAG,
+ flags=bfd.BFD_FLAG_AUTH_PRESENT,
+ state=bfd.BFD_STATE_DOWN, detect_mult=3, my_discr=1,
+ your_discr=0, desired_min_tx_interval=1000000,
+ required_min_rx_interval=1000000,
+ required_min_echo_rx_interval=0,
+ auth_cls=auth_cls)
+
+ jsondict = bfd1.to_jsondict()
+ bfd2 = bfd.bfd.from_jsondict(jsondict['bfd'])
+ eq_(str(bfd1), str(bfd2))
+
+ def test_json_with_auth_sha1(self):
+ auth_cls = bfd.KeyedSHA1(auth_key_id=2, seq=16859,
+ auth_key=self.auth_keys[2])
+
+ bfd1 = bfd.bfd(ver=1, diag=bfd.BFD_DIAG_NO_DIAG,
+ flags=bfd.BFD_FLAG_AUTH_PRESENT,
+ state=bfd.BFD_STATE_DOWN, detect_mult=3, my_discr=1,
+ your_discr=0, desired_min_tx_interval=1000000,
+ required_min_rx_interval=1000000,
+ required_min_echo_rx_interval=0,
+ auth_cls=auth_cls)
+
+ jsondict = bfd1.to_jsondict()
+ bfd2 = bfd.bfd.from_jsondict(jsondict['bfd'])
+ eq_(str(bfd1), str(bfd2))
diff --git a/tests/unit/packet/test_bgp.py b/tests/unit/packet/test_bgp.py
new file mode 100644
index 00000000..2211fc4c
--- /dev/null
+++ b/tests/unit/packet/test_bgp.py
@@ -0,0 +1,813 @@
+# Copyright (C) 2013,2014 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2013,2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
+#
+# 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.
+
+from __future__ import print_function
+
+import logging
+import os
+import sys
+
+import unittest
+from nose.tools import eq_
+from nose.tools import ok_
+
+from ryu.utils import binary_str
+from ryu.lib import pcaplib
+from ryu.lib.packet import packet
+from ryu.lib.packet import bgp
+from ryu.lib.packet import afi
+from ryu.lib.packet import safi
+
+
+LOG = logging.getLogger(__name__)
+
+BGP4_PACKET_DATA_DIR = os.path.join(
+ os.path.dirname(sys.modules[__name__].__file__), '../../packet_data/bgp4/')
+
+PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT = (
+ bgp.BGPPathAttributePmsiTunnel.TYPE_NO_TUNNEL_INFORMATION_PRESENT
+)
+PMSI_TYPE_INGRESS_REPLICATION = (
+ bgp.BGPPathAttributePmsiTunnel.TYPE_INGRESS_REPLICATION
+)
+
+RULES_BASE = [
+ # port='>=8000'
+ bgp.FlowSpecPort(
+ operator=(bgp.FlowSpecPort.GT | bgp.FlowSpecPort.EQ),
+ value=8000),
+ # port='&<=9000'
+ bgp.FlowSpecPort(
+ operator=(bgp.FlowSpecPort.AND | bgp.FlowSpecPort.LT |
+ bgp.FlowSpecPort.EQ),
+ value=9000),
+ # port='==80'
+ bgp.FlowSpecPort(operator=bgp.FlowSpecPort.EQ, value=80),
+ # dst_port=8080
+ bgp.FlowSpecDestPort(operator=bgp.FlowSpecDestPort.EQ, value=8080),
+ # dst_port='>9000'
+ bgp.FlowSpecDestPort(operator=bgp.FlowSpecDestPort.GT, value=9000),
+ # dst_port='&<9050'
+ bgp.FlowSpecDestPort(
+ operator=(bgp.FlowSpecDestPort.AND | bgp.FlowSpecDestPort.LT),
+ value=9050),
+ # dst_port='<=1000'
+ bgp.FlowSpecDestPort(
+ operator=(bgp.FlowSpecDestPort.LT | bgp.FlowSpecDestPort.EQ),
+ value=1000),
+ # src_port='<=9090'
+ bgp.FlowSpecSrcPort(
+ operator=(bgp.FlowSpecSrcPort.LT | bgp.FlowSpecSrcPort.EQ),
+ value=9090),
+ # src_port='& >=9080'
+ bgp.FlowSpecSrcPort(
+ operator=(bgp.FlowSpecSrcPort.AND | bgp.FlowSpecSrcPort.GT |
+ bgp.FlowSpecSrcPort.EQ),
+ value=9080),
+ # src_port='<10100'
+ bgp.FlowSpecSrcPort(
+ operator=bgp.FlowSpecSrcPort.LT, value=10100),
+ # src_port='>10000'
+ bgp.FlowSpecSrcPort(
+ operator=(bgp.FlowSpecSrcPort.AND | bgp.FlowSpecSrcPort.GT),
+ value=10000),
+ # icmp_type=0
+ bgp.FlowSpecIcmpType(operator=bgp.FlowSpecIcmpType.EQ, value=0),
+ # icmp_code=6
+ bgp.FlowSpecIcmpCode(operator=bgp.FlowSpecIcmpCode.EQ, value=6),
+ # tcp_flags='ACK+FIN'
+ bgp.FlowSpecTCPFlags(
+ operator=0, # Partial match
+ value=(bgp.FlowSpecTCPFlags.SYN | bgp.FlowSpecTCPFlags.ACK)),
+ # tcp_flags='&!=URGENT'
+ bgp.FlowSpecTCPFlags(
+ operator=(bgp.FlowSpecTCPFlags.AND | bgp.FlowSpecTCPFlags.NOT),
+ value=bgp.FlowSpecTCPFlags.URGENT),
+ # packet_len=1000
+ bgp.FlowSpecPacketLen(
+ operator=bgp.FlowSpecPacketLen.EQ, value=1000),
+ # packet_len=1100
+ bgp.FlowSpecPacketLen(
+ operator=(bgp.FlowSpecTCPFlags.AND | bgp.FlowSpecPacketLen.EQ),
+ value=1100),
+ # dscp=22
+ bgp.FlowSpecDSCP(operator=bgp.FlowSpecDSCP.EQ, value=22),
+ # dscp=24
+ bgp.FlowSpecDSCP(operator=bgp.FlowSpecDSCP.EQ, value=24),
+]
+
+RULES_L2VPN_BASE = [
+ # ether_type=0x0800
+ bgp.FlowSpecEtherType(operator=bgp.FlowSpecEtherType.EQ, value=0x0800),
+ # source_mac='12:34:56:78:90:AB'
+ bgp.FlowSpecSourceMac(addr='12:34:56:78:90:AB', length=6),
+ # dest_mac='DE:EF:C0:FF:EE:DD'
+ bgp.FlowSpecDestinationMac(addr='BE:EF:C0:FF:EE:DD', length=6),
+ # llc_dsap=0x42
+ bgp.FlowSpecLLCDSAP(operator=bgp.FlowSpecLLCDSAP.EQ, value=0x42),
+ # llc_ssap=0x42
+ bgp.FlowSpecLLCSSAP(operator=bgp.FlowSpecLLCSSAP.EQ, value=0x42),
+ # llc_control=100
+ bgp.FlowSpecLLCControl(operator=bgp.FlowSpecLLCControl.EQ, value=100),
+ # snap=0x12345
+ bgp.FlowSpecSNAP(operator=bgp.FlowSpecSNAP.EQ, value=0x12345),
+ # vlan_id='>4000'
+ bgp.FlowSpecVLANID(operator=bgp.FlowSpecVLANID.GT, value=4000),
+ # vlan_cos='>=3'
+ bgp.FlowSpecVLANCoS(
+ operator=(bgp.FlowSpecVLANCoS.GT | bgp.FlowSpecVLANCoS.EQ), value=3),
+ # inner_vlan_id='<3000'
+ bgp.FlowSpecInnerVLANID(operator=bgp.FlowSpecInnerVLANID.LT, value=3000),
+ # inner_vlan_cos='<=5'
+ bgp.FlowSpecInnerVLANCoS(
+ operator=(bgp.FlowSpecInnerVLANCoS.LT | bgp.FlowSpecInnerVLANCoS.EQ),
+ value=5),
+]
+
+
+class Test_bgp(unittest.TestCase):
+ """ Test case for ryu.lib.packet.bgp
+ """
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_open1(self):
+ msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.1')
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ eq_(len(msg), 29)
+ eq_(rest, b'')
+
+ def test_open2(self):
+ opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200,
+ cap_value=b'hoge'),
+ bgp.BGPOptParamCapabilityGracefulRestart(flags=0,
+ time=120,
+ tuples=[]),
+ bgp.BGPOptParamCapabilityRouteRefresh(),
+ bgp.BGPOptParamCapabilityCiscoRouteRefresh(),
+ bgp.BGPOptParamCapabilityMultiprotocol(
+ afi=afi.IP, safi=safi.MPLS_VPN),
+ bgp.BGPOptParamCapabilityCarryingLabelInfo(),
+ bgp.BGPOptParamCapabilityFourOctetAsNumber(
+ as_number=1234567),
+ bgp.BGPOptParamUnknown(type_=99, value=b'fuga')]
+ msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2',
+ opt_param=opt_param)
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ ok_(len(msg) > 29)
+ eq_(rest, b'')
+
+ def test_update1(self):
+ msg = bgp.BGPUpdate()
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ eq_(len(msg), 23)
+ eq_(rest, b'')
+
+ def test_update2(self):
+ withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=1,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=3,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=7,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=32,
+ addr='192.0.2.13')]
+ mp_nlri = [
+ bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0',
+ route_dist='100:100',
+ labels=[1, 2, 3]),
+ bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192',
+ route_dist='10.0.0.1:10000',
+ labels=[5, 6, 7, 8]),
+ ]
+ mp_nlri2 = [
+ bgp.LabelledIPAddrPrefix(24, '192.168.0.0', labels=[1, 2, 3])
+ ]
+ mp_nlri_v6 = [
+ bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:1111::',
+ route_dist='200:200',
+ labels=[1, 2, 3]),
+ bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:2222::',
+ route_dist='10.0.0.1:10000',
+ labels=[5, 6, 7, 8]),
+ ]
+ mp_nlri2_v6 = [
+ bgp.LabelledIP6AddrPrefix(64, '2001:db8:3333::', labels=[1, 2, 3])
+ ]
+ communities = [
+ bgp.BGP_COMMUNITY_NO_EXPORT,
+ bgp.BGP_COMMUNITY_NO_ADVERTISE,
+ ]
+ ecommunities = [
+ bgp.BGPTwoOctetAsSpecificExtendedCommunity(
+ subtype=1, as_number=65500, local_administrator=3908876543),
+ bgp.BGPFourOctetAsSpecificExtendedCommunity(
+ subtype=2, as_number=10000000, local_administrator=59876),
+ bgp.BGPIPv4AddressSpecificExtendedCommunity(
+ subtype=3, ipv4_address='192.0.2.1',
+ local_administrator=65432),
+ bgp.BGPOpaqueExtendedCommunity(subtype=13, opaque=b'abcdef'),
+ bgp.BGPEncapsulationExtendedCommunity(
+ subtype=0x0c, tunnel_type=10),
+ bgp.BGPEvpnMacMobilityExtendedCommunity(
+ subtype=0, flags=0xff, sequence_number=0x11223344),
+ bgp.BGPEvpnEsiLabelExtendedCommunity(
+ subtype=1, flags=0xff, label=b'\xFF\xFF\xFF'),
+ bgp.BGPEvpnEsiLabelExtendedCommunity(
+ subtype=1, flags=0xff, mpls_label=0xfffff),
+ bgp.BGPEvpnEsiLabelExtendedCommunity(
+ subtype=1, flags=0xff, vni=0xffffff),
+ bgp.BGPEvpnEsImportRTExtendedCommunity(
+ subtype=2, es_import="aa:bb:cc:dd:ee:ff"),
+ bgp.BGPUnknownExtendedCommunity(type_=99, value=b'abcdefg'),
+ ]
+ path_attributes = [
+ bgp.BGPPathAttributeOrigin(value=1),
+ bgp.BGPPathAttributeAsPath(value=[[1000], {1001, 1002},
+ [1003, 1004]]),
+ bgp.BGPPathAttributeNextHop(value='192.0.2.199'),
+ bgp.BGPPathAttributeMultiExitDisc(value=2000000000),
+ bgp.BGPPathAttributeLocalPref(value=1000000000),
+ bgp.BGPPathAttributeAtomicAggregate(),
+ bgp.BGPPathAttributeAggregator(as_number=40000,
+ addr='192.0.2.99'),
+ bgp.BGPPathAttributeCommunities(communities=communities),
+ bgp.BGPPathAttributeOriginatorId(value='10.1.1.1'),
+ bgp.BGPPathAttributeClusterList(value=['1.1.1.1', '2.2.2.2']),
+ bgp.BGPPathAttributeExtendedCommunities(communities=ecommunities),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
+ label=b'\xFF\xFF\xFF'),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
+ tunnel_id=None),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
+ mpls_label=0xfffff,
+ tunnel_id=bgp.PmsiTunnelIdIngressReplication(
+ tunnel_endpoint_ip="1.1.1.1")),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
+ vni=0xffffff,
+ tunnel_id=bgp.PmsiTunnelIdIngressReplication(
+ tunnel_endpoint_ip="aa:bb:cc::dd:ee:ff")),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=2,
+ label=b'\xFF\xFF\xFF',
+ tunnel_id=bgp.PmsiTunnelIdUnknown(value=b'test')),
+ bgp.BGPPathAttributeAs4Path(value=[[1000000], {1000001, 1002},
+ [1003, 1000004]]),
+ bgp.BGPPathAttributeAs4Aggregator(as_number=100040000,
+ addr='192.0.2.99'),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
+ next_hop='1.1.1.1',
+ nlri=mp_nlri),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_LABEL,
+ next_hop='1.1.1.1',
+ nlri=mp_nlri2),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_VPN,
+ next_hop=['2001:db8::1'],
+ nlri=mp_nlri_v6),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_LABEL,
+ next_hop=['2001:db8::1',
+ 'fe80::1'],
+ nlri=mp_nlri2_v6),
+ bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
+ withdrawn_routes=mp_nlri),
+ bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300 * b'bar')
+ ]
+ nlri = [
+ bgp.BGPNLRI(length=24, addr='203.0.113.1'),
+ bgp.BGPNLRI(length=16, addr='203.0.113.0')
+ ]
+ msg = bgp.BGPUpdate(withdrawn_routes=withdrawn_routes,
+ path_attributes=path_attributes,
+ nlri=nlri)
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ ok_(len(msg) > 23)
+ eq_(rest, b'')
+
+ def test_keepalive(self):
+ msg = bgp.BGPKeepAlive()
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ eq_(len(msg), 19)
+ eq_(rest, b'')
+
+ def test_notification(self):
+ data = b'hoge'
+ msg = bgp.BGPNotification(error_code=1, error_subcode=2, data=data)
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ eq_(len(msg), 21 + len(data))
+ eq_(rest, b'')
+
+ def test_route_refresh(self):
+ msg = bgp.BGPRouteRefresh(afi=afi.IP, safi=safi.MPLS_VPN)
+ binmsg = msg.serialize()
+ msg2, _, rest = bgp.BGPMessage.parser(binmsg)
+ eq_(str(msg), str(msg2))
+ eq_(len(msg), 23)
+ eq_(rest, b'')
+
+ def test_stream_parser(self):
+ msgs = [
+ bgp.BGPNotification(error_code=1, error_subcode=2, data=b'foo'),
+ bgp.BGPNotification(error_code=3, error_subcode=4, data=b'bar'),
+ bgp.BGPNotification(error_code=5, error_subcode=6, data=b'baz'),
+ ]
+ binmsgs = b''.join([bytes(msg.serialize()) for msg in msgs])
+ sp = bgp.StreamParser()
+ results = []
+ for b in binmsgs:
+ for m in sp.parse(b):
+ results.append(m)
+ eq_(str(results), str(msgs))
+
+ def test_parser(self):
+ files = [
+ 'bgp4-open',
+ 'bgp4-update',
+ 'bgp4-update_ipv6',
+ 'bgp4-update_vpnv6',
+ 'bgp4-keepalive',
+ 'evpn_esi_arbitrary',
+ 'evpn_esi_lacp',
+ 'evpn_esi_l2_bridge',
+ 'evpn_esi_mac_base',
+ 'evpn_esi_router_id',
+ 'evpn_esi_as_based',
+ 'evpn_nlri_eth_a-d',
+ 'evpn_nlri_mac_ip_ad',
+ 'evpn_nlri_inc_multi_eth_tag',
+ 'evpn_nlri_eth_seg',
+ 'evpn_nlri_ip_prefix',
+ 'flowspec_nlri_ipv4',
+ 'flowspec_nlri_vpn4',
+ 'flowspec_nlri_ipv6',
+ 'flowspec_nlri_vpn6',
+ 'flowspec_nlri_l2vpn',
+ 'flowspec_action_traffic_rate',
+ 'flowspec_action_traffic_action',
+ 'flowspec_action_redirect',
+ 'flowspec_action_traffic_marking',
+ ]
+
+ for f in files:
+ LOG.debug('*** testing %s ...', f)
+ for _, buf in pcaplib.Reader(
+ open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb')):
+ # Checks if BGP message can be parsed as expected.
+ pkt = packet.Packet(buf)
+ ok_(isinstance(pkt.protocols[-1], bgp.BGPMessage),
+ 'Failed to parse BGP message: %s' % pkt)
+
+ # Checks if BGP message can be serialized as expected.
+ pkt.serialize()
+ eq_(buf, pkt.data,
+ "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))
+
+ def test_vlan_action_parser(self):
+ action = bgp.BGPFlowSpecVlanActionCommunity(
+ actions_1=(bgp.BGPFlowSpecVlanActionCommunity.POP |
+ bgp.BGPFlowSpecVlanActionCommunity.SWAP),
+ vlan_1=3000,
+ cos_1=3,
+ actions_2=bgp.BGPFlowSpecVlanActionCommunity.PUSH,
+ vlan_2=4000,
+ cos_2=2,
+ )
+ binmsg = action.serialize()
+ msg, rest = bgp.BGPFlowSpecVlanActionCommunity.parse(binmsg)
+ eq_(str(action), str(msg))
+ eq_(rest, b'')
+
+ def test_tpid_action_parser(self):
+ action = bgp.BGPFlowSpecTPIDActionCommunity(
+ actions=(bgp.BGPFlowSpecTPIDActionCommunity.TI |
+ bgp.BGPFlowSpecTPIDActionCommunity.TO),
+ tpid_1=5,
+ tpid_2=6,
+ )
+ binmsg = action.serialize()
+ msg, rest = bgp.BGPFlowSpecTPIDActionCommunity.parse(binmsg)
+ eq_(str(action), str(msg))
+ eq_(rest, b'')
+
+ def test_json1(self):
+ opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200,
+ cap_value=b'hoge'),
+ bgp.BGPOptParamCapabilityRouteRefresh(),
+ bgp.BGPOptParamCapabilityMultiprotocol(
+ afi=afi.IP, safi=safi.MPLS_VPN),
+ bgp.BGPOptParamCapabilityFourOctetAsNumber(
+ as_number=1234567),
+ bgp.BGPOptParamUnknown(type_=99, value=b'fuga')]
+ msg1 = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2',
+ opt_param=opt_param)
+ jsondict = msg1.to_jsondict()
+ msg2 = bgp.BGPOpen.from_jsondict(jsondict['BGPOpen'])
+ eq_(str(msg1), str(msg2))
+
+ def test_json2(self):
+ withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=1,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=3,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=7,
+ addr='192.0.2.13'),
+ bgp.BGPWithdrawnRoute(length=32,
+ addr='192.0.2.13')]
+ mp_nlri = [
+ bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0',
+ route_dist='100:100',
+ labels=[1, 2, 3]),
+ bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192',
+ route_dist='10.0.0.1:10000',
+ labels=[5, 6, 7, 8]),
+ ]
+ mp_nlri2 = [
+ bgp.LabelledIPAddrPrefix(24, '192.168.0.0', labels=[1, 2, 3])
+ ]
+ mp_nlri_v6 = [
+ bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:1111::',
+ route_dist='200:200',
+ labels=[1, 2, 3]),
+ bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:2222::',
+ route_dist='10.0.0.1:10000',
+ labels=[5, 6, 7, 8]),
+ ]
+ mp_nlri2_v6 = [
+ bgp.LabelledIP6AddrPrefix(64, '2001:db8:3333::', labels=[1, 2, 3])
+ ]
+ communities = [
+ bgp.BGP_COMMUNITY_NO_EXPORT,
+ bgp.BGP_COMMUNITY_NO_ADVERTISE,
+ ]
+ ecommunities = [
+ bgp.BGPTwoOctetAsSpecificExtendedCommunity(
+ subtype=1, as_number=65500, local_administrator=3908876543),
+ bgp.BGPFourOctetAsSpecificExtendedCommunity(
+ subtype=2, as_number=10000000, local_administrator=59876),
+ bgp.BGPIPv4AddressSpecificExtendedCommunity(
+ subtype=3, ipv4_address='192.0.2.1',
+ local_administrator=65432),
+ bgp.BGPOpaqueExtendedCommunity(subtype=13, opaque=b'abcdef'),
+ bgp.BGPEncapsulationExtendedCommunity(
+ subtype=0x0c, tunnel_type=10),
+ bgp.BGPEvpnMacMobilityExtendedCommunity(
+ subtype=0, flags=0xff, sequence_number=0x11223344),
+ bgp.BGPEvpnEsiLabelExtendedCommunity(
+ subtype=1, flags=0xff, label=b'\xFF\xFF\xFF'),
+ bgp.BGPEvpnEsiLabelExtendedCommunity(
+ subtype=1, flags=0xff, mpls_label=0xfffff),
+ bgp.BGPEvpnEsiLabelExtendedCommunity(
+ subtype=1, flags=0xff, vni=0xffffff),
+ bgp.BGPEvpnEsImportRTExtendedCommunity(
+ subtype=2, es_import="aa:bb:cc:dd:ee:ff"),
+ bgp.BGPUnknownExtendedCommunity(type_=99, value=b'abcdefg'),
+ ]
+ path_attributes = [
+ bgp.BGPPathAttributeOrigin(value=1),
+ bgp.BGPPathAttributeAsPath(value=[[1000], {1001, 1002},
+ [1003, 1004]]),
+ bgp.BGPPathAttributeNextHop(value='192.0.2.199'),
+ bgp.BGPPathAttributeMultiExitDisc(value=2000000000),
+ bgp.BGPPathAttributeLocalPref(value=1000000000),
+ bgp.BGPPathAttributeAtomicAggregate(),
+ bgp.BGPPathAttributeAggregator(as_number=40000,
+ addr='192.0.2.99'),
+ bgp.BGPPathAttributeCommunities(communities=communities),
+ bgp.BGPPathAttributeExtendedCommunities(communities=ecommunities),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
+ label=b'\xFF\xFF\xFF'),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
+ tunnel_id=None),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
+ mpls_label=0xfffff,
+ tunnel_id=bgp.PmsiTunnelIdIngressReplication(
+ tunnel_endpoint_ip="1.1.1.1")),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
+ vni=0xffffff,
+ tunnel_id=bgp.PmsiTunnelIdIngressReplication(
+ tunnel_endpoint_ip="aa:bb:cc::dd:ee:ff")),
+ bgp.BGPPathAttributePmsiTunnel(
+ pmsi_flags=1,
+ tunnel_type=2,
+ label=b'\xFF\xFF\xFF',
+ tunnel_id=bgp.PmsiTunnelIdUnknown(value=b'test')),
+ bgp.BGPPathAttributeAs4Path(value=[[1000000], {1000001, 1002},
+ [1003, 1000004]]),
+ bgp.BGPPathAttributeAs4Aggregator(as_number=100040000,
+ addr='192.0.2.99'),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
+ next_hop='1.1.1.1',
+ nlri=mp_nlri),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_LABEL,
+ next_hop='1.1.1.1',
+ nlri=mp_nlri2),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_VPN,
+ next_hop=['2001:db8::1'],
+ nlri=mp_nlri_v6),
+ bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_LABEL,
+ next_hop=['2001:db8::1',
+ 'fe80::1'],
+ nlri=mp_nlri2_v6),
+ bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
+ withdrawn_routes=mp_nlri),
+ bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300 * b'bar')
+ ]
+ nlri = [
+ bgp.BGPNLRI(length=24, addr='203.0.113.1'),
+ bgp.BGPNLRI(length=16, addr='203.0.113.0')
+ ]
+ msg1 = bgp.BGPUpdate(withdrawn_routes=withdrawn_routes,
+ path_attributes=path_attributes,
+ nlri=nlri)
+ jsondict = msg1.to_jsondict()
+ msg2 = bgp.BGPUpdate.from_jsondict(jsondict['BGPUpdate'])
+ eq_(str(msg1), str(msg2))
+
+ def test_flowspec_user_interface_ipv4(self):
+ rules = RULES_BASE + [
+ # dst_prefix='10.0.0.0/24
+ bgp.FlowSpecDestPrefix(addr='10.0.0.0', length=24),
+ # src_prefix='20.0.0.1/24'
+ bgp.FlowSpecSrcPrefix(addr='20.0.0.0', length=24),
+ # ip_proto='6'
+ bgp.FlowSpecIPProtocol(
+ operator=bgp.FlowSpecIPProtocol.EQ, value=6),
+ # fragment='LF'
+ bgp.FlowSpecFragment(
+ operator=0, # Partial match
+ value=bgp.FlowSpecFragment.LF),
+ # fragment='==FF'
+ bgp.FlowSpecFragment(
+ operator=bgp.FlowSpecFragment.MATCH,
+ value=bgp.FlowSpecFragment.FF),
+ # fragment='&==ISF'
+ bgp.FlowSpecFragment(
+ operator=(bgp.FlowSpecFragment.AND |
+ bgp.FlowSpecFragment.MATCH),
+ value=bgp.FlowSpecFragment.ISF),
+ # fragment='!=DF'
+ bgp.FlowSpecFragment(
+ operator=bgp.FlowSpecFragment.NOT,
+ value=bgp.FlowSpecFragment.DF)
+ ]
+
+ msg = bgp.FlowSpecIPv4NLRI.from_user(
+ dst_prefix='10.0.0.0/24',
+ src_prefix='20.0.0.0/24',
+ ip_proto='6',
+ port='>=8000 & <=9000 | ==80',
+ dst_port='8080 >9000&<9050 | <=1000',
+ src_port='<=9090 & >=9080 <10100 & >10000',
+ icmp_type=0,
+ icmp_code=6,
+ tcp_flags='SYN+ACK & !=URGENT',
+ packet_len='1000 & 1100',
+ dscp='22 24',
+ fragment='LF ==FF&==ISF | !=DF')
+ msg2 = bgp.FlowSpecIPv4NLRI(rules=rules)
+ binmsg = msg.serialize()
+ binmsg2 = msg2.serialize()
+ eq_(str(msg), str(msg2))
+ eq_(binary_str(binmsg), binary_str(binmsg2))
+ msg3, rest = bgp.FlowSpecIPv4NLRI.parser(binmsg)
+ eq_(str(msg), str(msg3))
+ eq_(rest, b'')
+
+ def test_flowspec_user_interface_vpv4(self):
+ rules = RULES_BASE + [
+ # dst_prefix='10.0.0.0/24
+ bgp.FlowSpecDestPrefix(addr='10.0.0.0', length=24),
+ # src_prefix='20.0.0.1/24'
+ bgp.FlowSpecSrcPrefix(addr='20.0.0.0', length=24),
+ # ip_proto='6'
+ bgp.FlowSpecIPProtocol(
+ operator=bgp.FlowSpecIPProtocol.EQ, value=6),
+ # fragment='LF'
+ bgp.FlowSpecFragment(
+ operator=0, # Partial match
+ value=bgp.FlowSpecFragment.LF),
+ # fragment='==FF'
+ bgp.FlowSpecFragment(
+ operator=bgp.FlowSpecFragment.MATCH,
+ value=bgp.FlowSpecFragment.FF),
+ # fragment='&==ISF'
+ bgp.FlowSpecFragment(
+ operator=(bgp.FlowSpecFragment.AND |
+ bgp.FlowSpecFragment.MATCH),
+ value=bgp.FlowSpecFragment.ISF),
+ # fragment='!=DF'
+ bgp.FlowSpecFragment(
+ operator=bgp.FlowSpecFragment.NOT,
+ value=bgp.FlowSpecFragment.DF)
+ ]
+ msg = bgp.FlowSpecVPNv4NLRI.from_user(
+ route_dist='65001:250',
+ dst_prefix='10.0.0.0/24',
+ src_prefix='20.0.0.0/24',
+ ip_proto='6',
+ port='>=8000 & <=9000 | ==80',
+ dst_port='8080 >9000&<9050 | <=1000',
+ src_port='<=9090 & >=9080 <10100 & >10000',
+ icmp_type=0,
+ icmp_code=6,
+ tcp_flags='SYN+ACK & !=URGENT',
+ packet_len='1000 & 1100',
+ dscp='22 24',
+ fragment='LF ==FF&==ISF | !=DF')
+ msg2 = bgp.FlowSpecVPNv4NLRI(route_dist='65001:250', rules=rules)
+ binmsg = msg.serialize()
+ binmsg2 = msg2.serialize()
+ eq_(str(msg), str(msg2))
+ eq_(binary_str(binmsg), binary_str(binmsg2))
+ msg3, rest = bgp.FlowSpecVPNv4NLRI.parser(binmsg)
+ eq_(str(msg), str(msg3))
+ eq_(rest, b'')
+
+ def test_flowspec_user_interface_ipv6(self):
+ rules = RULES_BASE + [
+ # dst_prefix='2001:2/128/32'
+ bgp.FlowSpecIPv6DestPrefix(
+ addr='2001::2', offset=32, length=128),
+ # src_prefix='3002::3/128'
+ bgp.FlowSpecIPv6SrcPrefix(
+ addr='3002::3', length=128),
+ # ip_proto='6'
+ bgp.FlowSpecNextHeader(
+ operator=bgp.FlowSpecNextHeader.EQ, value=6),
+ # fragment='LF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=0, # Partial match
+ value=bgp.FlowSpecFragment.LF),
+ # fragment='==FF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=bgp.FlowSpecFragment.MATCH,
+ value=bgp.FlowSpecFragment.FF),
+ # fragment='&==ISF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=(bgp.FlowSpecFragment.AND |
+ bgp.FlowSpecFragment.MATCH),
+ value=bgp.FlowSpecFragment.ISF),
+ # fragment='!=LF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=bgp.FlowSpecFragment.NOT,
+ value=bgp.FlowSpecFragment.LF),
+ # flowlabel='100'
+ bgp.FlowSpecIPv6FlowLabel(
+ operator=bgp.FlowSpecIPv6FlowLabel.EQ,
+ value=100),
+ ]
+ msg = bgp.FlowSpecIPv6NLRI.from_user(
+ dst_prefix='2001::2/128/32',
+ src_prefix='3002::3/128',
+ next_header='6',
+ port='>=8000 & <=9000 | ==80',
+ dst_port='8080 >9000&<9050 | <=1000',
+ src_port='<=9090 & >=9080 <10100 & >10000',
+ icmp_type=0,
+ icmp_code=6,
+ tcp_flags='SYN+ACK & !=URGENT',
+ packet_len='1000 & 1100',
+ dscp='22 24',
+ fragment='LF ==FF&==ISF | !=LF',
+ flow_label=100,
+ )
+ msg2 = bgp.FlowSpecIPv6NLRI(rules=rules)
+ binmsg = msg.serialize()
+ binmsg2 = msg2.serialize()
+ eq_(str(msg), str(msg2))
+ eq_(binary_str(binmsg), binary_str(binmsg2))
+ msg3, rest = bgp.FlowSpecIPv6NLRI.parser(binmsg)
+ eq_(str(msg), str(msg3))
+ eq_(rest, b'')
+
+ def test_flowspec_user_interface_vpnv6(self):
+ rules = RULES_BASE + [
+ # dst_prefix='2001:2/128/32'
+ bgp.FlowSpecIPv6DestPrefix(
+ addr='2001::2', offset=32, length=128),
+ # src_prefix='3002::3/128'
+ bgp.FlowSpecIPv6SrcPrefix(
+ addr='3002::3', length=128),
+ # ip_proto='6'
+ bgp.FlowSpecNextHeader(
+ operator=bgp.FlowSpecNextHeader.EQ, value=6),
+ # fragment='LF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=0, # Partial match
+ value=bgp.FlowSpecFragment.LF),
+ # fragment='==FF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=bgp.FlowSpecFragment.MATCH,
+ value=bgp.FlowSpecFragment.FF),
+ # fragment='&==ISF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=(bgp.FlowSpecFragment.AND |
+ bgp.FlowSpecFragment.MATCH),
+ value=bgp.FlowSpecFragment.ISF),
+ # fragment='!=LF'
+ bgp.FlowSpecIPv6Fragment(
+ operator=bgp.FlowSpecFragment.NOT,
+ value=bgp.FlowSpecFragment.LF),
+ # flowlabel='100'
+ bgp.FlowSpecIPv6FlowLabel(
+ operator=bgp.FlowSpecIPv6FlowLabel.EQ,
+ value=100),
+ ]
+ msg = bgp.FlowSpecVPNv6NLRI.from_user(
+ route_dist='65001:250',
+ dst_prefix='2001::2/128/32',
+ src_prefix='3002::3/128',
+ next_header='6',
+ port='>=8000 & <=9000 | ==80',
+ dst_port='8080 >9000&<9050 | <=1000',
+ src_port='<=9090 & >=9080 <10100 & >10000',
+ icmp_type=0,
+ icmp_code=6,
+ tcp_flags='SYN+ACK & !=URGENT',
+ packet_len='1000 & 1100',
+ dscp='22 24',
+ fragment='LF ==FF&==ISF | !=LF',
+ flow_label=100,
+ )
+ msg2 = bgp.FlowSpecVPNv6NLRI(route_dist='65001:250', rules=rules)
+ binmsg = msg.serialize()
+ binmsg2 = msg2.serialize()
+ eq_(str(msg), str(msg2))
+ eq_(binary_str(binmsg), binary_str(binmsg2))
+ msg3, rest = bgp.FlowSpecVPNv6NLRI.parser(binmsg)
+ eq_(str(msg), str(msg3))
+ eq_(rest, b'')
+
+ def test_flowspec_user_interface_l2vpn(self):
+ rules = RULES_L2VPN_BASE
+ msg = bgp.FlowSpecL2VPNNLRI.from_user(
+ route_dist='65001:250',
+ ether_type=0x0800,
+ src_mac='12:34:56:78:90:AB',
+ dst_mac='BE:EF:C0:FF:EE:DD',
+ llc_dsap=0x42,
+ llc_ssap=0x42,
+ llc_control=100,
+ snap=0x12345,
+ vlan_id='>4000',
+ vlan_cos='>=3',
+ inner_vlan_id='<3000',
+ inner_vlan_cos='<=5',
+ )
+ msg2 = bgp.FlowSpecL2VPNNLRI(route_dist='65001:250', rules=rules)
+ binmsg = msg.serialize()
+ binmsg2 = msg2.serialize()
+ eq_(str(msg), str(msg2))
+ eq_(binary_str(binmsg), binary_str(binmsg2))
+ msg3, rest = bgp.FlowSpecL2VPNNLRI.parser(binmsg)
+ eq_(str(msg), str(msg3))
+ eq_(rest, b'')
diff --git a/tests/unit/packet/test_bmp.py b/tests/unit/packet/test_bmp.py
new file mode 100644
index 00000000..f93b8014
--- /dev/null
+++ b/tests/unit/packet/test_bmp.py
@@ -0,0 +1,136 @@
+# Copyright (C) 2014 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 unittest
+from nose.tools import eq_
+from nose.tools import ok_
+from time import time
+
+from ryu.lib.packet import bmp
+from ryu.lib.packet import bgp
+from ryu.lib.packet import afi
+from ryu.lib.packet import safi
+
+
+class Test_bmp(unittest.TestCase):
+ """ Test case for ryu.lib.packet.bmp
+ """
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def _time(self):
+ # time() can give sub-microsecond precision, which results
+ # in an assertion failure
+ return round(time(), 6)
+
+ def test_route_monitoring(self):
+ update = bgp.BGPUpdate()
+ msg = bmp.BMPRouteMonitoring(bgp_update=update,
+ peer_type=bmp.BMP_PEER_TYPE_GLOBAL,
+ is_post_policy=True,
+ peer_distinguisher=0,
+ peer_address='192.0.2.1',
+ peer_as=30000,
+ peer_bgp_id='192.0.2.1',
+ timestamp=self._time())
+ binmsg = msg.serialize()
+ msg2, rest = bmp.BMPMessage.parser(binmsg)
+ eq_(msg.to_jsondict(), msg2.to_jsondict())
+ eq_(rest, b'')
+
+ def test_statistics_report(self):
+ stats = [{'type': bmp.BMP_STAT_TYPE_REJECTED, 'value': 100},
+ {'type': bmp.BMP_STAT_TYPE_DUPLICATE_PREFIX, 'value': 200},
+ {'type': bmp.BMP_STAT_TYPE_DUPLICATE_WITHDRAW, 'value': 300},
+ {'type': bmp.BMP_STAT_TYPE_ADJ_RIB_IN, 'value': 100000},
+ {'type': bmp.BMP_STAT_TYPE_LOC_RIB, 'value': 500000}]
+ msg = bmp.BMPStatisticsReport(stats=stats,
+ peer_type=bmp.BMP_PEER_TYPE_GLOBAL,
+ is_post_policy=True,
+ peer_distinguisher=0,
+ peer_address='192.0.2.1',
+ peer_as=30000,
+ peer_bgp_id='192.0.2.1',
+ timestamp=self._time())
+ binmsg = msg.serialize()
+ msg2, rest = bmp.BMPMessage.parser(binmsg)
+ eq_(msg.to_jsondict(), msg2.to_jsondict())
+ eq_(rest, b'')
+
+ def test_peer_down_notification(self):
+ reason = bmp.BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION
+ data = b'hoge'
+ data = bgp.BGPNotification(error_code=1, error_subcode=2, data=data)
+ msg = bmp.BMPPeerDownNotification(reason=reason, data=data,
+ peer_type=bmp.BMP_PEER_TYPE_GLOBAL,
+ is_post_policy=True,
+ peer_distinguisher=0,
+ peer_address='192.0.2.1',
+ peer_as=30000,
+ peer_bgp_id='192.0.2.1',
+ timestamp=self._time())
+ binmsg = msg.serialize()
+ msg2, rest = bmp.BMPMessage.parser(binmsg)
+ eq_(msg.to_jsondict(), msg2.to_jsondict())
+ eq_(rest, b'')
+
+ def test_peer_up_notification(self):
+ opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200,
+ cap_value=b'hoge'),
+ bgp.BGPOptParamCapabilityRouteRefresh(),
+ bgp.BGPOptParamCapabilityMultiprotocol(
+ afi=afi.IP, safi=safi.MPLS_VPN)]
+ open_message = bgp.BGPOpen(my_as=40000, bgp_identifier='192.0.2.2',
+ opt_param=opt_param)
+ msg = bmp.BMPPeerUpNotification(local_address='192.0.2.2',
+ local_port=179,
+ remote_port=11089,
+ sent_open_message=open_message,
+ received_open_message=open_message,
+ peer_type=bmp.BMP_PEER_TYPE_GLOBAL,
+ is_post_policy=True,
+ peer_distinguisher=0,
+ peer_address='192.0.2.1',
+ peer_as=30000,
+ peer_bgp_id='192.0.2.1',
+ timestamp=self._time())
+ binmsg = msg.serialize()
+ msg2, rest = bmp.BMPMessage.parser(binmsg)
+ eq_(msg.to_jsondict(), msg2.to_jsondict())
+ eq_(rest, b'')
+
+ def test_initiation(self):
+ initiation_info = [{'type': bmp.BMP_INIT_TYPE_STRING,
+ 'value': u'This is Ryu BGP BMP message'}]
+ msg = bmp.BMPInitiation(info=initiation_info)
+ binmsg = msg.serialize()
+ msg2, rest = bmp.BMPMessage.parser(binmsg)
+ eq_(msg.to_jsondict(lambda v: v), msg2.to_jsondict(lambda v: v))
+ eq_(rest, b'')
+
+ def test_termination(self):
+ termination_info = [{'type': bmp.BMP_TERM_TYPE_STRING,
+ 'value': u'Session administatively closed'},
+ {'type': bmp.BMP_TERM_TYPE_REASON,
+ 'value': bmp.BMP_TERM_REASON_ADMIN}]
+ msg = bmp.BMPTermination(info=termination_info)
+ binmsg = msg.serialize()
+ msg2, rest = bmp.BMPMessage.parser(binmsg)
+ eq_(msg.to_jsondict(lambda v: v), msg2.to_jsondict(lambda v: v))
+ eq_(rest, b'')
diff --git a/tests/unit/packet/test_bpdu.py b/tests/unit/packet/test_bpdu.py
new file mode 100644
index 00000000..1ef8cf58
--- /dev/null
+++ b/tests/unit/packet/test_bpdu.py
@@ -0,0 +1,469 @@
+# Copyright (C) 2013 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 unittest
+import logging
+import struct
+
+from nose.tools import eq_
+from ryu.lib.packet import bpdu
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_ConfigurationBPDUs(unittest.TestCase):
+ """ Test case for ConfigurationBPDUs
+ """
+
+ def setUp(self):
+ self.protocol_id = bpdu.PROTOCOL_IDENTIFIER
+ self.version_id = bpdu.ConfigurationBPDUs.VERSION_ID
+ self.bpdu_type = bpdu.ConfigurationBPDUs.BPDU_TYPE
+ self.flags = 0b00000001
+ self.root_priority = 4096
+ self.root_system_id_extension = 1
+ self.root_mac_address = '12:34:56:78:9a:bc'
+ self.root_path_cost = 2
+ self.bridge_priority = 8192
+ self.bridge_system_id_extension = 3
+ self.bridge_mac_address = 'aa:aa:aa:aa:aa:aa'
+ self.port_priority = 16
+ self.port_number = 4
+ self.message_age = 5
+ self.max_age = 6
+ self.hello_time = 7
+ self.forward_delay = 8
+
+ self.msg = bpdu.ConfigurationBPDUs(
+ flags=self.flags,
+ root_priority=self.root_priority,
+ root_system_id_extension=self.root_system_id_extension,
+ root_mac_address=self.root_mac_address,
+ root_path_cost=self.root_path_cost,
+ bridge_priority=self.bridge_priority,
+ bridge_system_id_extension=self.bridge_system_id_extension,
+ bridge_mac_address=self.bridge_mac_address,
+ port_priority=self.port_priority,
+ port_number=self.port_number,
+ message_age=self.message_age,
+ max_age=self.max_age,
+ hello_time=self.hello_time,
+ forward_delay=self.forward_delay)
+
+ self.fmt = (bpdu.bpdu._PACK_STR
+ + bpdu.ConfigurationBPDUs._PACK_STR[1:])
+ self.buf = struct.pack(self.fmt,
+ self.protocol_id, self.version_id,
+ self.bpdu_type, self.flags,
+ bpdu.ConfigurationBPDUs.encode_bridge_id(
+ self.root_priority,
+ self.root_system_id_extension,
+ self.root_mac_address),
+ self.root_path_cost,
+ bpdu.ConfigurationBPDUs.encode_bridge_id(
+ self.bridge_priority,
+ self.bridge_system_id_extension,
+ self.bridge_mac_address),
+ bpdu.ConfigurationBPDUs.encode_port_id(
+ self.port_priority,
+ self.port_number),
+ bpdu.ConfigurationBPDUs._encode_timer(
+ self.message_age),
+ bpdu.ConfigurationBPDUs._encode_timer(
+ self.max_age),
+ bpdu.ConfigurationBPDUs._encode_timer(
+ self.hello_time),
+ bpdu.ConfigurationBPDUs._encode_timer(
+ self.forward_delay))
+
+ def test_init(self):
+ eq_(self.protocol_id, self.msg._protocol_id)
+ eq_(self.version_id, self.msg._version_id)
+ eq_(self.bpdu_type, self.msg._bpdu_type)
+ eq_(self.flags, self.msg.flags)
+ eq_(self.root_priority, self.msg.root_priority)
+ eq_(self.root_system_id_extension,
+ self.msg.root_system_id_extension)
+ eq_(self.root_mac_address, self.msg.root_mac_address)
+ eq_(self.root_path_cost, self.msg.root_path_cost)
+ eq_(self.bridge_priority, self.msg.bridge_priority)
+ eq_(self.bridge_system_id_extension,
+ self.msg.bridge_system_id_extension)
+ eq_(self.bridge_mac_address, self.msg.bridge_mac_address)
+ eq_(self.port_priority, self.msg.port_priority)
+ eq_(self.port_number, self.msg.port_number)
+ eq_(self.message_age, self.msg.message_age)
+ eq_(self.max_age, self.msg.max_age)
+ eq_(self.hello_time, self.msg.hello_time)
+ eq_(self.forward_delay, self.msg.forward_delay)
+
+ def test_parser(self):
+ r1, r2, _ = bpdu.bpdu.parser(self.buf)
+
+ eq_(type(r1), type(self.msg))
+ eq_(r1._protocol_id, self.protocol_id)
+ eq_(r1._version_id, self.version_id)
+ eq_(r1._bpdu_type, self.bpdu_type)
+ eq_(r1.flags, self.flags)
+ eq_(r1.root_priority, self.root_priority)
+ eq_(r1.root_system_id_extension, self.root_system_id_extension)
+ eq_(r1.root_mac_address, self.root_mac_address)
+ eq_(r1.root_path_cost, self.root_path_cost)
+ eq_(r1.bridge_priority, self.bridge_priority)
+ eq_(r1.bridge_system_id_extension, self.bridge_system_id_extension)
+ eq_(r1.bridge_mac_address, self.bridge_mac_address)
+ eq_(r1.port_priority, self.port_priority)
+ eq_(r1.port_number, self.port_number)
+ eq_(r1.message_age, self.message_age)
+ eq_(r1.max_age, self.max_age)
+ eq_(r1.hello_time, self.hello_time)
+ eq_(r1.forward_delay, self.forward_delay)
+ eq_(r2, None)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.msg.serialize(data, prev)
+ res = struct.unpack(self.fmt, buf)
+
+ eq_(res[0], self.protocol_id)
+ eq_(res[1], self.version_id)
+ eq_(res[2], self.bpdu_type)
+ eq_(res[3], self.flags)
+ eq_(bpdu.ConfigurationBPDUs._decode_bridge_id(res[4]),
+ (self.root_priority,
+ self.root_system_id_extension,
+ self.root_mac_address))
+ eq_(res[5], self.root_path_cost)
+ eq_(bpdu.ConfigurationBPDUs._decode_bridge_id(res[6]),
+ (self.bridge_priority,
+ self.bridge_system_id_extension,
+ self.bridge_mac_address))
+ eq_(bpdu.ConfigurationBPDUs._decode_port_id(res[7]),
+ (self.port_priority,
+ self.port_number))
+ eq_(bpdu.ConfigurationBPDUs._decode_timer(res[8]), self.message_age)
+ eq_(bpdu.ConfigurationBPDUs._decode_timer(res[9]), self.max_age)
+ eq_(bpdu.ConfigurationBPDUs._decode_timer(res[10]), self.hello_time)
+ eq_(bpdu.ConfigurationBPDUs._decode_timer(res[11]), self.forward_delay)
+
+ def test_json(self):
+ jsondict = self.msg.to_jsondict()
+ msg = bpdu.ConfigurationBPDUs.from_jsondict(
+ jsondict['ConfigurationBPDUs'])
+ eq_(str(self.msg), str(msg))
+
+
+class Test_TopologyChangeNotificationBPDUs(unittest.TestCase):
+ """ Test case for TopologyChangeNotificationBPDUs
+ """
+
+ def setUp(self):
+ self.protocol_id = bpdu.PROTOCOL_IDENTIFIER
+ self.version_id = bpdu.TopologyChangeNotificationBPDUs.VERSION_ID
+ self.bpdu_type = bpdu.TopologyChangeNotificationBPDUs.BPDU_TYPE
+
+ self.msg = bpdu.TopologyChangeNotificationBPDUs()
+
+ self.fmt = bpdu.bpdu._PACK_STR
+ self.buf = struct.pack(self.fmt,
+ self.protocol_id,
+ self.version_id,
+ self.bpdu_type)
+
+ def test_init(self):
+ eq_(self.protocol_id, self.msg._protocol_id)
+ eq_(self.version_id, self.msg._version_id)
+ eq_(self.bpdu_type, self.msg._bpdu_type)
+
+ def test_parser(self):
+ r1, r2, _ = bpdu.bpdu.parser(self.buf)
+
+ eq_(type(r1), type(self.msg))
+ eq_(r1._protocol_id, self.protocol_id)
+ eq_(r1._version_id, self.version_id)
+ eq_(r1._bpdu_type, self.bpdu_type)
+ eq_(r2, None)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.msg.serialize(data, prev)
+ res = struct.unpack(self.fmt, buf)
+
+ eq_(res[0], self.protocol_id)
+ eq_(res[1], self.version_id)
+ eq_(res[2], self.bpdu_type)
+
+ def test_json(self):
+ jsondict = self.msg.to_jsondict()
+ msg = bpdu.TopologyChangeNotificationBPDUs.from_jsondict(
+ jsondict['TopologyChangeNotificationBPDUs'])
+ eq_(str(self.msg), str(msg))
+
+
+class Test_RstBPDUs(unittest.TestCase):
+ """ Test case for RstBPDUs
+ """
+
+ def setUp(self):
+ self.protocol_id = bpdu.PROTOCOL_IDENTIFIER
+ self.version_id = bpdu.RstBPDUs.VERSION_ID
+ self.bpdu_type = bpdu.RstBPDUs.BPDU_TYPE
+ self.flags = 0b01111110
+ self.root_priority = 4096
+ self.root_system_id_extension = 1
+ self.root_mac_address = '12:34:56:78:9a:bc'
+ self.root_path_cost = 2
+ self.bridge_priority = 8192
+ self.bridge_system_id_extension = 3
+ self.bridge_mac_address = 'aa:aa:aa:aa:aa:aa'
+ self.port_priority = 16
+ self.port_number = 4
+ self.message_age = 5
+ self.max_age = 6
+ self.hello_time = 7
+ self.forward_delay = 8
+ self.version_1_length = bpdu.VERSION_1_LENGTH
+
+ self.msg = bpdu.RstBPDUs(
+ flags=self.flags,
+ root_priority=self.root_priority,
+ root_system_id_extension=self.root_system_id_extension,
+ root_mac_address=self.root_mac_address,
+ root_path_cost=self.root_path_cost,
+ bridge_priority=self.bridge_priority,
+ bridge_system_id_extension=self.bridge_system_id_extension,
+ bridge_mac_address=self.bridge_mac_address,
+ port_priority=self.port_priority,
+ port_number=self.port_number,
+ message_age=self.message_age,
+ max_age=self.max_age,
+ hello_time=self.hello_time,
+ forward_delay=self.forward_delay)
+
+ self.fmt = (bpdu.bpdu._PACK_STR
+ + bpdu.ConfigurationBPDUs._PACK_STR[1:]
+ + bpdu.RstBPDUs._PACK_STR[1:])
+ self.buf = struct.pack(self.fmt,
+ self.protocol_id, self.version_id,
+ self.bpdu_type, self.flags,
+ bpdu.RstBPDUs.encode_bridge_id(
+ self.root_priority,
+ self.root_system_id_extension,
+ self.root_mac_address),
+ self.root_path_cost,
+ bpdu.RstBPDUs.encode_bridge_id(
+ self.bridge_priority,
+ self.bridge_system_id_extension,
+ self.bridge_mac_address),
+ bpdu.RstBPDUs.encode_port_id(
+ self.port_priority,
+ self.port_number),
+ bpdu.RstBPDUs._encode_timer(self.message_age),
+ bpdu.RstBPDUs._encode_timer(self.max_age),
+ bpdu.RstBPDUs._encode_timer(self.hello_time),
+ bpdu.RstBPDUs._encode_timer(self.forward_delay),
+ self.version_1_length)
+
+ def test_init(self):
+ eq_(self.protocol_id, self.msg._protocol_id)
+ eq_(self.version_id, self.msg._version_id)
+ eq_(self.bpdu_type, self.msg._bpdu_type)
+ eq_(self.flags, self.msg.flags)
+ eq_(self.root_priority, self.msg.root_priority)
+ eq_(self.root_system_id_extension,
+ self.msg.root_system_id_extension)
+ eq_(self.root_mac_address, self.msg.root_mac_address)
+ eq_(self.root_path_cost, self.msg.root_path_cost)
+ eq_(self.bridge_priority, self.msg.bridge_priority)
+ eq_(self.bridge_system_id_extension,
+ self.msg.bridge_system_id_extension)
+ eq_(self.bridge_mac_address, self.msg.bridge_mac_address)
+ eq_(self.port_priority, self.msg.port_priority)
+ eq_(self.port_number, self.msg.port_number)
+ eq_(self.message_age, self.msg.message_age)
+ eq_(self.max_age, self.msg.max_age)
+ eq_(self.hello_time, self.msg.hello_time)
+ eq_(self.forward_delay, self.msg.forward_delay)
+ eq_(self.version_1_length, self.msg._version_1_length)
+
+ def test_parser(self):
+ r1, r2, _ = bpdu.bpdu.parser(self.buf)
+
+ eq_(type(r1), type(self.msg))
+ eq_(r1._protocol_id, self.protocol_id)
+ eq_(r1._version_id, self.version_id)
+ eq_(r1._bpdu_type, self.bpdu_type)
+ eq_(r1.flags, self.flags)
+ eq_(r1.root_priority, self.root_priority)
+ eq_(r1.root_system_id_extension, self.root_system_id_extension)
+ eq_(r1.root_mac_address, self.root_mac_address)
+ eq_(r1.root_path_cost, self.root_path_cost)
+ eq_(r1.bridge_priority, self.bridge_priority)
+ eq_(r1.bridge_system_id_extension, self.bridge_system_id_extension)
+ eq_(r1.bridge_mac_address, self.bridge_mac_address)
+ eq_(r1.port_priority, self.port_priority)
+ eq_(r1.port_number, self.port_number)
+ eq_(r1.message_age, self.message_age)
+ eq_(r1.max_age, self.max_age)
+ eq_(r1.hello_time, self.hello_time)
+ eq_(r1.forward_delay, self.forward_delay)
+ eq_(r1._version_1_length, self.version_1_length)
+ eq_(r2, None)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.msg.serialize(data, prev)
+ res = struct.unpack(self.fmt, buf)
+
+ eq_(res[0], self.protocol_id)
+ eq_(res[1], self.version_id)
+ eq_(res[2], self.bpdu_type)
+ eq_(res[3], self.flags)
+ eq_(bpdu.RstBPDUs._decode_bridge_id(res[4]),
+ (self.root_priority,
+ self.root_system_id_extension,
+ self.root_mac_address))
+ eq_(res[5], self.root_path_cost)
+ eq_(bpdu.RstBPDUs._decode_bridge_id(res[6]),
+ (self.bridge_priority,
+ self.bridge_system_id_extension,
+ self.bridge_mac_address))
+ eq_(bpdu.RstBPDUs._decode_port_id(res[7]),
+ (self.port_priority,
+ self.port_number))
+ eq_(bpdu.RstBPDUs._decode_timer(res[8]), self.message_age)
+ eq_(bpdu.RstBPDUs._decode_timer(res[9]), self.max_age)
+ eq_(bpdu.RstBPDUs._decode_timer(res[10]), self.hello_time)
+ eq_(bpdu.RstBPDUs._decode_timer(res[11]), self.forward_delay)
+ eq_(res[12], self.version_1_length)
+
+ def test_json(self):
+ jsondict = self.msg.to_jsondict()
+ msg = bpdu.RstBPDUs.from_jsondict(jsondict['RstBPDUs'])
+ eq_(str(self.msg), str(msg))
+
+
+class Test_UnknownVersion(unittest.TestCase):
+ """ Test case for unknown BPDU version
+ """
+
+ def setUp(self):
+ self.protocol_id = bpdu.PROTOCOL_IDENTIFIER
+ self.version_id = 111 # Unknown version
+ self.bpdu_type = bpdu.RstBPDUs.BPDU_TYPE
+ self.flags = 0b01111110
+ self.root_priority = 4096
+ self.root_system_id_extension = 1
+ self.root_mac_address = '12:34:56:78:9a:bc'
+ self.root_path_cost = 2
+ self.bridge_priority = 8192
+ self.bridge_system_id_extension = 3
+ self.bridge_mac_address = 'aa:aa:aa:aa:aa:aa'
+ self.port_priority = 16
+ self.port_number = 4
+ self.message_age = 5
+ self.max_age = 6
+ self.hello_time = 7
+ self.forward_delay = 8
+ self.version_1_length = bpdu.VERSION_1_LENGTH
+
+ self.fmt = (bpdu.bpdu._PACK_STR
+ + bpdu.ConfigurationBPDUs._PACK_STR[1:]
+ + bpdu.RstBPDUs._PACK_STR[1:])
+ self.buf = struct.pack(self.fmt,
+ self.protocol_id, self.version_id,
+ self.bpdu_type, self.flags,
+ bpdu.RstBPDUs.encode_bridge_id(
+ self.root_priority,
+ self.root_system_id_extension,
+ self.root_mac_address),
+ self.root_path_cost,
+ bpdu.RstBPDUs.encode_bridge_id(
+ self.bridge_priority,
+ self.bridge_system_id_extension,
+ self.bridge_mac_address),
+ bpdu.RstBPDUs.encode_port_id(
+ self.port_priority,
+ self.port_number),
+ bpdu.RstBPDUs._encode_timer(self.message_age),
+ bpdu.RstBPDUs._encode_timer(self.max_age),
+ bpdu.RstBPDUs._encode_timer(self.hello_time),
+ bpdu.RstBPDUs._encode_timer(self.forward_delay),
+ self.version_1_length)
+
+ def test_parser(self):
+ r1, r2, _ = bpdu.bpdu.parser(self.buf)
+ eq_(r1, self.buf)
+ eq_(r2, None)
+
+
+class Test_UnknownType(unittest.TestCase):
+ """ Test case for unknown BPDU type
+ """
+
+ def setUp(self):
+ self.protocol_id = bpdu.PROTOCOL_IDENTIFIER
+ self.version_id = bpdu.RstBPDUs.VERSION_ID
+ self.bpdu_type = 222 # Unknown type
+ self.flags = 0b01111110
+ self.root_priority = 4096
+ self.root_system_id_extension = 1
+ self.root_mac_address = '12:34:56:78:9a:bc'
+ self.root_path_cost = 2
+ self.bridge_priority = 8192
+ self.bridge_system_id_extension = 3
+ self.bridge_mac_address = 'aa:aa:aa:aa:aa:aa'
+ self.port_priority = 16
+ self.port_number = 4
+ self.message_age = 5
+ self.max_age = 6
+ self.hello_time = 7
+ self.forward_delay = 8
+ self.version_1_length = bpdu.VERSION_1_LENGTH
+
+ self.fmt = (bpdu.bpdu._PACK_STR
+ + bpdu.ConfigurationBPDUs._PACK_STR[1:]
+ + bpdu.RstBPDUs._PACK_STR[1:])
+ self.buf = struct.pack(self.fmt,
+ self.protocol_id, self.version_id,
+ self.bpdu_type, self.flags,
+ bpdu.RstBPDUs.encode_bridge_id(
+ self.root_priority,
+ self.root_system_id_extension,
+ self.root_mac_address),
+ self.root_path_cost,
+ bpdu.RstBPDUs.encode_bridge_id(
+ self.bridge_priority,
+ self.bridge_system_id_extension,
+ self.bridge_mac_address),
+ bpdu.RstBPDUs.encode_port_id(
+ self.port_priority,
+ self.port_number),
+ bpdu.RstBPDUs._encode_timer(self.message_age),
+ bpdu.RstBPDUs._encode_timer(self.max_age),
+ bpdu.RstBPDUs._encode_timer(self.hello_time),
+ bpdu.RstBPDUs._encode_timer(self.forward_delay),
+ self.version_1_length)
+
+ def test_parser(self):
+ r1, r2, _ = bpdu.bpdu.parser(self.buf)
+ eq_(r1, self.buf)
+ eq_(r2, None)
diff --git a/tests/unit/packet/test_cfm.py b/tests/unit/packet/test_cfm.py
new file mode 100644
index 00000000..fb0749d7
--- /dev/null
+++ b/tests/unit/packet/test_cfm.py
@@ -0,0 +1,1761 @@
+# Copyright (C) 2013 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 unittest
+import logging
+import inspect
+import six
+import struct
+
+from nose.tools import *
+from ryu.lib import addrconv
+from ryu.lib.packet import cfm
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_cfm(unittest.TestCase):
+
+ def setUp(self):
+ self.message = cfm.cc_message()
+ self.ins = cfm.cfm(self.message)
+ data = bytearray()
+ prev = None
+ self.buf = self.ins.serialize(data, prev)
+
+ def setUp_cc_message(self):
+ self.cc_message_md_lv = 1
+ self.cc_message_version = 1
+ self.cc_message_rdi = 1
+ self.cc_message_interval = 1
+ self.cc_message_seq_num = 123
+ self.cc_message_mep_id = 4
+ self.cc_message_md_name_format = 4
+ self.cc_message_md_name_length = 0
+ self.cc_message_md_name = b"hoge"
+ self.cc_message_short_ma_name_format = 2
+ self.cc_message_short_ma_name_length = 0
+ self.cc_message_short_ma_name = b"pakeratta"
+ self.cc_message_md_name_txfcf = 11
+ self.cc_message_md_name_rxfcb = 22
+ self.cc_message_md_name_txfcb = 33
+ self.cc_message_tlvs = [
+ cfm.sender_id_tlv(),
+ cfm.port_status_tlv(),
+ cfm.data_tlv(),
+ cfm.interface_status_tlv(),
+ cfm.reply_ingress_tlv(),
+ cfm.reply_egress_tlv(),
+ cfm.ltm_egress_identifier_tlv(),
+ cfm.ltr_egress_identifier_tlv(),
+ cfm.organization_specific_tlv(),
+ ]
+ self.message = cfm.cc_message(
+ self.cc_message_md_lv,
+ self.cc_message_version,
+ self.cc_message_rdi,
+ self.cc_message_interval,
+ self.cc_message_seq_num,
+ self.cc_message_mep_id,
+ self.cc_message_md_name_format,
+ self.cc_message_md_name_length,
+ self.cc_message_md_name,
+ self.cc_message_short_ma_name_format,
+ self.cc_message_short_ma_name_length,
+ self.cc_message_short_ma_name,
+ self.cc_message_tlvs
+ )
+ self.ins = cfm.cfm(self.message)
+ data = bytearray()
+ prev = None
+ self.buf = self.ins.serialize(data, prev)
+
+ def setUp_loopback_message(self):
+ self.loopback_message_md_lv = 1
+ self.loopback_message_version = 1
+ self.loopback_message_transaction_id = 12345
+ self.loopback_message_tlvs = [
+ cfm.sender_id_tlv(),
+ cfm.port_status_tlv(),
+ cfm.data_tlv(),
+ cfm.interface_status_tlv(),
+ cfm.reply_ingress_tlv(),
+ cfm.reply_egress_tlv(),
+ cfm.ltm_egress_identifier_tlv(),
+ cfm.ltr_egress_identifier_tlv(),
+ cfm.organization_specific_tlv(),
+ ]
+ self.message = cfm.loopback_message(
+ self.loopback_message_md_lv,
+ self.loopback_message_version,
+ self.loopback_message_transaction_id,
+ self.loopback_message_tlvs)
+ self.ins = cfm.cfm(self.message)
+ data = bytearray()
+ prev = None
+ self.buf = self.ins.serialize(data, prev)
+
+ def setUp_loopback_reply(self):
+ self.loopback_reply_md_lv = 1
+ self.loopback_reply_version = 1
+ self.loopback_reply_transaction_id = 12345
+ self.loopback_reply_tlvs = [
+ cfm.sender_id_tlv(),
+ cfm.port_status_tlv(),
+ cfm.data_tlv(),
+ cfm.interface_status_tlv(),
+ cfm.reply_ingress_tlv(),
+ cfm.reply_egress_tlv(),
+ cfm.ltm_egress_identifier_tlv(),
+ cfm.ltr_egress_identifier_tlv(),
+ cfm.organization_specific_tlv(),
+ ]
+ self.message = cfm.loopback_reply(
+ self.loopback_reply_md_lv,
+ self.loopback_reply_version,
+ self.loopback_reply_transaction_id,
+ self.loopback_reply_tlvs)
+ self.ins = cfm.cfm(self.message)
+ data = bytearray()
+ prev = None
+ self.buf = self.ins.serialize(data, prev)
+
+ def setUp_link_trace_message(self):
+ self.link_trace_message_md_lv = 1
+ self.link_trace_message_version = 1
+ self.link_trace_message_use_fdb_only = 1
+ self.link_trace_message_transaction_id = 12345
+ self.link_trace_message_ttl = 123
+ self.link_trace_message_ltm_orig_addr = '11:22:33:44:55:66'
+ self.link_trace_message_ltm_targ_addr = '77:88:99:aa:cc:dd'
+ self.link_trace_message_tlvs = [
+ cfm.sender_id_tlv(),
+ cfm.port_status_tlv(),
+ cfm.data_tlv(),
+ cfm.interface_status_tlv(),
+ cfm.reply_ingress_tlv(),
+ cfm.reply_egress_tlv(),
+ cfm.ltm_egress_identifier_tlv(),
+ cfm.ltr_egress_identifier_tlv(),
+ cfm.organization_specific_tlv(),
+ ]
+ self.message = cfm.link_trace_message(
+ self.link_trace_message_md_lv,
+ self.link_trace_message_version,
+ self.link_trace_message_use_fdb_only,
+ self.link_trace_message_transaction_id,
+ self.link_trace_message_ttl,
+ self.link_trace_message_ltm_orig_addr,
+ self.link_trace_message_ltm_targ_addr,
+ self.link_trace_message_tlvs)
+ self.ins = cfm.cfm(self.message)
+ data = bytearray()
+ prev = None
+ self.buf = self.ins.serialize(data, prev)
+
+ def setUp_link_trace_reply(self):
+ self.link_trace_reply_md_lv = 1
+ self.link_trace_reply_version = 1
+ self.link_trace_reply_use_fdb_only = 1
+ self.link_trace_reply_fwd_yes = 0
+ self.link_trace_reply_terminal_mep = 1
+ self.link_trace_reply_transaction_id = 5432
+ self.link_trace_reply_ttl = 123
+ self.link_trace_reply_relay_action = 3
+ self.link_trace_reply_tlvs = [
+ cfm.sender_id_tlv(),
+ cfm.port_status_tlv(),
+ cfm.data_tlv(),
+ cfm.interface_status_tlv(),
+ cfm.reply_ingress_tlv(),
+ cfm.reply_egress_tlv(),
+ cfm.ltm_egress_identifier_tlv(),
+ cfm.ltr_egress_identifier_tlv(),
+ cfm.organization_specific_tlv(),
+ ]
+ self.message = cfm.link_trace_reply(
+ self.link_trace_reply_md_lv,
+ self.link_trace_reply_version,
+ self.link_trace_reply_use_fdb_only,
+ self.link_trace_reply_fwd_yes,
+ self.link_trace_reply_terminal_mep,
+ self.link_trace_reply_transaction_id,
+ self.link_trace_reply_ttl,
+ self.link_trace_reply_relay_action,
+ self.link_trace_reply_tlvs)
+ self.ins = cfm.cfm(self.message)
+ data = bytearray()
+ prev = None
+ self.buf = self.ins.serialize(data, prev)
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(str(self.message), str(self.ins.op))
+
+ def test_init_cc_message(self):
+ self.setUp_cc_message()
+ self.test_init()
+
+ def test_init_loopback_message(self):
+ self.setUp_loopback_message()
+ self.test_init()
+
+ def test_init_loopback_reply(self):
+ self.setUp_loopback_reply()
+ self.test_init()
+
+ def test_init_link_trace_message(self):
+ self.setUp_link_trace_message()
+ self.test_init()
+
+ def test_init_link_trace_reply(self):
+ self.setUp_link_trace_reply()
+ self.test_init()
+
+ def test_parser(self):
+ _res = self.ins.parser(six.binary_type(self.buf))
+
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(str(self.message), str(res.op))
+
+ def test_parser_with_cc_message(self):
+ self.setUp_cc_message()
+ self.test_parser()
+
+ def test_parser_with_loopback_message(self):
+ self.setUp_loopback_message()
+ self.test_parser()
+
+ def test_parser_with_loopback_reply(self):
+ self.setUp_loopback_reply()
+ self.test_parser()
+
+ def test_parser_with_link_trace_message(self):
+ self.setUp_link_trace_message()
+ self.test_parser()
+
+ def test_parser_with_link_trace_reply(self):
+ self.setUp_link_trace_reply()
+ self.test_parser()
+
+ def test_serialize(self):
+ pass
+
+ def test_serialize_with_cc_message(self):
+ self.setUp_cc_message()
+ self.test_serialize()
+ data = bytearray()
+ prev = None
+ buf = self.ins.serialize(data, prev)
+ cc_message = cfm.cc_message.parser(six.binary_type(buf))
+ eq_(repr(self.message), repr(cc_message))
+
+ def test_serialize_with_loopback_message(self):
+ self.setUp_loopback_message()
+ self.test_serialize()
+ data = bytearray()
+ prev = None
+ buf = self.ins.serialize(data, prev)
+ loopback_message = cfm.loopback_message.parser(six.binary_type(buf))
+ eq_(repr(self.message), repr(loopback_message))
+
+ def test_serialize_with_loopback_reply(self):
+ self.setUp_loopback_reply()
+ self.test_serialize()
+ data = bytearray()
+ prev = None
+ buf = self.ins.serialize(data, prev)
+ loopback_reply = cfm.loopback_reply.parser(six.binary_type(buf))
+ eq_(repr(self.message), repr(loopback_reply))
+
+ def test_serialize_with_link_trace_message(self):
+ self.setUp_link_trace_message()
+ self.test_serialize()
+ data = bytearray()
+ prev = None
+ buf = self.ins.serialize(data, prev)
+ link_trace_message = cfm.link_trace_message.parser(six.binary_type(buf))
+ eq_(repr(self.message), repr(link_trace_message))
+
+ def test_serialize_with_link_trace_reply(self):
+ self.setUp_link_trace_reply()
+ self.test_serialize()
+ data = bytearray()
+ prev = None
+ buf = self.ins.serialize(data, prev)
+ link_trace_reply = cfm.link_trace_reply.parser(six.binary_type(buf))
+ eq_(repr(self.message), repr(link_trace_reply))
+
+ def test_to_string(self):
+ cfm_values = {'op': self.message}
+ _cfm_str = ','.join(['%s=%s' % (k, cfm_values[k])
+ for k, v in inspect.getmembers(self.ins)
+ if k in cfm_values])
+ cfm_str = '%s(%s)' % (cfm.cfm.__name__, _cfm_str)
+ eq_(str(self.ins), cfm_str)
+ eq_(repr(self.ins), cfm_str)
+
+ def test_to_string_cc_message(self):
+ self.setUp_cc_message()
+ self.test_to_string()
+
+ def test_to_string_loopback_message(self):
+ self.setUp_loopback_message()
+ self.test_to_string()
+
+ def test_to_string_loopback_reply(self):
+ self.setUp_loopback_reply()
+ self.test_to_string()
+
+ def test_to_string_link_trace_message(self):
+ self.setUp_link_trace_message()
+ self.test_to_string()
+
+ def test_to_string_link_trace_reply(self):
+ self.setUp_link_trace_reply()
+ self.test_to_string()
+
+ def test_len(self):
+ pass
+
+ def test_len_cc_message(self):
+ self.setUp_cc_message()
+ eq_(len(self.ins), 0 + len(self.message))
+
+ def test_len_loopback_message(self):
+ self.setUp_loopback_message()
+ eq_(len(self.ins), 0 + len(self.message))
+
+ def test_len_loopback_reply(self):
+ self.setUp_loopback_reply()
+ eq_(len(self.ins), 0 + len(self.message))
+
+ def test_len_link_trace_message(self):
+ self.setUp_link_trace_message()
+ eq_(len(self.ins), 0 + len(self.message))
+
+ def test_len_link_trace_reply(self):
+ self.setUp_link_trace_reply()
+ eq_(len(self.ins), 0 + len(self.message))
+
+ def test_default_args(self):
+ pass
+
+ def test_json(self):
+ jsondict = self.ins.to_jsondict()
+ ins = cfm.cfm.from_jsondict(jsondict['cfm'])
+ eq_(str(self.ins), str(ins))
+
+ def test_json_with_cc_message(self):
+ self.setUp_cc_message()
+ self.test_json()
+
+ def test_json_with_loopback_message(self):
+ self.setUp_loopback_message()
+ self.test_json()
+
+ def test_json_with_loopback_reply(self):
+ self.setUp_loopback_reply()
+ self.test_json()
+
+ def test_json_with_link_trace_message(self):
+ self.setUp_link_trace_message()
+ self.test_json()
+
+ def test_json_with_link_trace_reply(self):
+ self.setUp_link_trace_reply()
+ self.test_json()
+
+
+class Test_cc_message(unittest.TestCase):
+
+ def setUp(self):
+ self.md_lv = 1
+ self.version = 1
+ self.opcode = cfm.CFM_CC_MESSAGE
+ self.rdi = 1
+ self.interval = 5
+ self.first_tlv_offset = cfm.cc_message._TLV_OFFSET
+ self.seq_num = 2
+ self.mep_id = 2
+ self.md_name_format = cfm.cc_message._MD_FMT_CHARACTER_STRING
+ self.md_name_length = 3
+ self.md_name = b"foo"
+ self.short_ma_name_format = 2
+ self.short_ma_name_length = 8
+ self.short_ma_name = b"hogehoge"
+ self.tlvs = [
+ ]
+ self.end_tlv = 0
+ self.ins = cfm.cc_message(
+ self.md_lv,
+ self.version,
+ self.rdi,
+ self.interval,
+ self.seq_num,
+ self.mep_id,
+ self.md_name_format,
+ self.md_name_length,
+ self.md_name,
+ self.short_ma_name_format,
+ self.short_ma_name_length,
+ self.short_ma_name,
+ self.tlvs
+ )
+
+ self.form = '!4BIH2B3s2B8s33x12x4xB'
+ self.buf = struct.pack(
+ self.form,
+ (self.md_lv << 5) | self.version,
+ self.opcode,
+ (self.rdi << 7) | self.interval,
+ self.first_tlv_offset,
+ self.seq_num,
+ self.mep_id,
+ self.md_name_format,
+ self.md_name_length,
+ self.md_name,
+ self.short_ma_name_format,
+ self.short_ma_name_length,
+ self.short_ma_name,
+ self.end_tlv
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.md_lv, self.ins.md_lv)
+ eq_(self.version, self.ins.version)
+ eq_(self.rdi, self.ins.rdi)
+ eq_(self.interval, self.ins.interval)
+ eq_(self.seq_num, self.ins.seq_num)
+ eq_(self.mep_id, self.ins.mep_id)
+ eq_(self.md_name_format, self.ins.md_name_format)
+ eq_(self.md_name_length, self.ins.md_name_length)
+ eq_(self.md_name, self.ins.md_name)
+ eq_(self.short_ma_name_format, self.ins.short_ma_name_format)
+ eq_(self.short_ma_name_length, self.ins.short_ma_name_length)
+ eq_(self.short_ma_name, self.ins.short_ma_name)
+ eq_(self.tlvs, self.ins.tlvs)
+
+ def test_parser(self):
+ _res = cfm.cc_message.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.md_lv, res.md_lv)
+ eq_(self.version, res.version)
+ eq_(self.rdi, res.rdi)
+ eq_(self.interval, res.interval)
+ eq_(self.seq_num, res.seq_num)
+ eq_(self.mep_id, res.mep_id)
+ eq_(self.md_name_format, res.md_name_format)
+ eq_(self.md_name_length, res.md_name_length)
+ eq_(self.md_name, res.md_name)
+ eq_(self.short_ma_name_format, res.short_ma_name_format)
+ eq_(self.short_ma_name_length, res.short_ma_name_length)
+ eq_(self.short_ma_name, res.short_ma_name)
+ eq_(self.tlvs, res.tlvs)
+
+ def test_parser_with_no_maintenance_domain_name_present(self):
+ form = '!4BIH3B8s37x12x4xB'
+ buf = struct.pack(
+ form,
+ (self.md_lv << 5) | self.version,
+ self.opcode,
+ (self.rdi << 7) | self.interval,
+ self.first_tlv_offset,
+ self.seq_num,
+ self.mep_id,
+ cfm.cc_message._MD_FMT_NO_MD_NAME_PRESENT,
+ self.short_ma_name_format,
+ self.short_ma_name_length,
+ self.short_ma_name,
+ self.end_tlv
+ )
+ _res = cfm.cc_message.parser(buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.md_lv, res.md_lv)
+ eq_(self.version, res.version)
+ eq_(self.rdi, res.rdi)
+ eq_(self.interval, res.interval)
+ eq_(self.seq_num, res.seq_num)
+ eq_(self.mep_id, res.mep_id)
+ eq_(cfm.cc_message._MD_FMT_NO_MD_NAME_PRESENT, res.md_name_format)
+ eq_(self.short_ma_name_format, res.short_ma_name_format)
+ eq_(self.short_ma_name_length, res.short_ma_name_length)
+ eq_(self.short_ma_name, res.short_ma_name)
+ eq_(self.tlvs, res.tlvs)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.rdi, res[2] >> 7)
+ eq_(self.interval, res[2] & 0x07)
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.seq_num, res[4])
+ eq_(self.mep_id, res[5])
+ eq_(self.md_name_format, res[6])
+ eq_(self.md_name_length, res[7])
+ eq_(self.md_name, res[8])
+ eq_(self.short_ma_name_format, res[9])
+ eq_(self.short_ma_name_length, res[10])
+ eq_(self.short_ma_name, res[11])
+ eq_(self.end_tlv, res[12])
+
+ def test_serialize_with_md_name_length_zero(self):
+ ins = cfm.cc_message(
+ self.md_lv,
+ self.version,
+ self.rdi,
+ self.interval,
+ self.seq_num,
+ self.mep_id,
+ self.md_name_format,
+ 0,
+ self.md_name,
+ self.short_ma_name_format,
+ 0,
+ self.short_ma_name,
+ self.tlvs
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.rdi, res[2] >> 7)
+ eq_(self.interval, res[2] & 0x07)
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.seq_num, res[4])
+ eq_(self.mep_id, res[5])
+ eq_(self.md_name_format, res[6])
+ eq_(self.md_name_length, res[7])
+ eq_(self.md_name, res[8])
+ eq_(self.short_ma_name_format, res[9])
+ eq_(self.short_ma_name_length, res[10])
+ eq_(self.short_ma_name, res[11])
+ eq_(self.end_tlv, res[12])
+
+ def test_serialize_with_no_maintenance_domain_name_present(self):
+ form = '!4BIH3B8s37x12x4xB'
+ ins = cfm.cc_message(
+ self.md_lv,
+ self.version,
+ self.rdi,
+ self.interval,
+ self.seq_num,
+ self.mep_id,
+ cfm.cc_message._MD_FMT_NO_MD_NAME_PRESENT,
+ 0,
+ self.md_name,
+ self.short_ma_name_format,
+ 0,
+ self.short_ma_name,
+ self.tlvs
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.rdi, res[2] >> 7)
+ eq_(self.interval, res[2] & 0x07)
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.seq_num, res[4])
+ eq_(self.mep_id, res[5])
+ eq_(cfm.cc_message._MD_FMT_NO_MD_NAME_PRESENT, res[6])
+ eq_(self.short_ma_name_format, res[7])
+ eq_(self.short_ma_name_length, res[8])
+ eq_(self.short_ma_name, res[9])
+ eq_(self.end_tlv, res[10])
+
+ def test_len(self):
+ # 75 octet (If tlv does not exist)
+ eq_(75, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.cc_message()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.cc_message._PACK_STR, six.binary_type(buf))
+ eq_(res[0] >> 5, 0)
+ eq_(res[0] & 0x1f, 0)
+ eq_(res[1], 1)
+ eq_(res[2] >> 7, 0)
+ eq_(res[2] & 0x07, 4)
+ eq_(res[3], 70)
+ eq_(res[4], 0)
+ eq_(res[5], 1)
+ eq_(res[6], 4)
+
+
+class Test_loopback_message(unittest.TestCase):
+
+ def setUp(self):
+ self.md_lv = 1
+ self.version = 1
+ self.opcode = cfm.CFM_LOOPBACK_MESSAGE
+ self.flags = 0
+ self.first_tlv_offset = cfm.loopback_message._TLV_OFFSET
+ self.transaction_id = 12345
+ self.tlvs = [
+ ]
+
+ self.end_tlv = 0
+ self.ins = cfm.loopback_message(
+ self.md_lv,
+ self.version,
+ self.transaction_id,
+ self.tlvs,
+ )
+ self.form = '!4BIB'
+ self.buf = struct.pack(
+ self.form,
+ (self.md_lv << 5) | self.version,
+ self.opcode,
+ self.flags,
+ self.first_tlv_offset,
+ self.transaction_id,
+ self.end_tlv
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.md_lv, self.ins.md_lv)
+ eq_(self.version, self.ins.version)
+ eq_(self.transaction_id, self.ins.transaction_id)
+ eq_(self.tlvs, self.ins.tlvs)
+
+ def test_parser(self):
+ _res = cfm.loopback_message.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.md_lv, res.md_lv)
+ eq_(self.version, res.version)
+ eq_(self.transaction_id, res.transaction_id)
+ eq_(self.tlvs, res.tlvs)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.flags, res[2])
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.transaction_id, res[4])
+ eq_(self.end_tlv, res[5])
+
+ def test_len(self):
+ # 9 octet (If tlv does not exist)
+ eq_(9, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.loopback_message()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.loopback_message._PACK_STR,
+ six.binary_type(buf))
+ eq_(res[0] >> 5, 0)
+ eq_(res[0] & 0x1f, 0)
+ eq_(res[1], 3)
+ eq_(res[2], 0)
+ eq_(res[3], 4)
+ eq_(res[4], 0)
+
+
+class Test_loopback_reply(unittest.TestCase):
+
+ def setUp(self):
+ self.md_lv = 1
+ self.version = 1
+ self.opcode = cfm.CFM_LOOPBACK_REPLY
+ self.flags = 0
+ self.first_tlv_offset = cfm.loopback_reply._TLV_OFFSET
+ self.transaction_id = 12345
+ self.tlvs = [
+ ]
+ self.end_tlv = 0
+ self.ins = cfm.loopback_reply(
+ self.md_lv,
+ self.version,
+ self.transaction_id,
+ self.tlvs,
+ )
+ self.form = '!4BIB'
+ self.buf = struct.pack(
+ self.form,
+ (self.md_lv << 5) | self.version,
+ self.opcode,
+ self.flags,
+ self.first_tlv_offset,
+ self.transaction_id,
+ self.end_tlv
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.md_lv, self.ins.md_lv)
+ eq_(self.version, self.ins.version)
+ eq_(self.transaction_id, self.ins.transaction_id)
+ eq_(self.tlvs, self.ins.tlvs)
+
+ def test_parser(self):
+ _res = cfm.loopback_reply.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.md_lv, res.md_lv)
+ eq_(self.version, res.version)
+ eq_(self.transaction_id, res.transaction_id)
+ eq_(self.tlvs, res.tlvs)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.flags, res[2])
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.transaction_id, res[4])
+ eq_(self.end_tlv, res[5])
+
+ def test_len(self):
+ # 9 octet (If tlv does not exist)
+ eq_(9, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.loopback_reply()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.loopback_reply._PACK_STR, six.binary_type(buf))
+ eq_(res[0] >> 5, 0)
+ eq_(res[0] & 0x1f, 0)
+ eq_(res[1], 2)
+ eq_(res[2], 0)
+ eq_(res[3], 4)
+ eq_(res[4], 0)
+
+
+class Test_link_trace_message(unittest.TestCase):
+
+ def setUp(self):
+ self.md_lv = 1
+ self.version = 1
+ self.opcode = cfm.CFM_LINK_TRACE_MESSAGE
+ self.use_fdb_only = 1
+ self.first_tlv_offset = cfm.link_trace_message._TLV_OFFSET
+ self.transaction_id = 12345
+ self.ttl = 55
+ self.ltm_orig_addr = "00:11:22:44:55:66"
+ self.ltm_targ_addr = "ab:cd:ef:23:12:65"
+ self.tlvs = [
+ ]
+
+ self.end_tlv = 0
+ self.ins = cfm.link_trace_message(
+ self.md_lv,
+ self.version,
+ self.use_fdb_only,
+ self.transaction_id,
+ self.ttl,
+ self.ltm_orig_addr,
+ self.ltm_targ_addr,
+ self.tlvs
+ )
+ self.form = '!4BIB6s6sB'
+ self.buf = struct.pack(
+ self.form,
+ (self.md_lv << 5) | self.version,
+ self.opcode,
+ self.use_fdb_only << 7,
+ self.first_tlv_offset,
+ self.transaction_id,
+ self.ttl,
+ addrconv.mac.text_to_bin(self.ltm_orig_addr),
+ addrconv.mac.text_to_bin(self.ltm_targ_addr),
+ self.end_tlv
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.md_lv, self.ins.md_lv)
+ eq_(self.version, self.ins.version)
+ eq_(self.use_fdb_only, self.ins.use_fdb_only)
+ eq_(self.transaction_id, self.ins.transaction_id)
+ eq_(self.ttl, self.ins.ttl)
+ eq_(self.ltm_orig_addr, self.ins.ltm_orig_addr)
+ eq_(self.ltm_targ_addr, self.ins.ltm_targ_addr)
+ eq_(self.tlvs, self.ins.tlvs)
+
+ def test_parser(self):
+ _res = cfm.link_trace_message.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.md_lv, res.md_lv)
+ eq_(self.version, res.version)
+ eq_(self.use_fdb_only, res.use_fdb_only)
+ eq_(self.transaction_id, res.transaction_id)
+ eq_(self.ttl, res.ttl)
+ eq_(self.ltm_orig_addr, res.ltm_orig_addr)
+ eq_(self.ltm_targ_addr, res.ltm_targ_addr)
+ eq_(self.tlvs, res.tlvs)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.use_fdb_only, res[2] >> 7)
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.transaction_id, res[4])
+ eq_(self.ttl, res[5])
+ eq_(addrconv.mac.text_to_bin(self.ltm_orig_addr), res[6])
+ eq_(addrconv.mac.text_to_bin(self.ltm_targ_addr), res[7])
+ eq_(self.end_tlv, res[8])
+
+ def test_len(self):
+ # 22 octet (If tlv does not exist)
+ eq_(22, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.link_trace_message()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.link_trace_message._PACK_STR, six.binary_type(buf))
+ eq_(res[0] >> 5, 0)
+ eq_(res[0] & 0x1f, 0)
+ eq_(res[1], 5)
+ eq_(res[2] >> 7, 1)
+ eq_(res[3], 17)
+ eq_(res[4], 0)
+ eq_(res[5], 64)
+ eq_(res[6], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+ eq_(res[7], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+
+class Test_link_trace_reply(unittest.TestCase):
+
+ def setUp(self):
+ self.md_lv = 1
+ self.version = 1
+ self.opcode = cfm.CFM_LINK_TRACE_REPLY
+ self.use_fdb_only = 1
+ self.fwd_yes = 0
+ self.terminal_mep = 1
+ self.first_tlv_offset = cfm.link_trace_reply._TLV_OFFSET
+ self.transaction_id = 12345
+ self.ttl = 55
+ self.relay_action = 2
+ self.ltm_orig_addr = "00:11:22:aa:bb:cc"
+ self.ltm_targ_addr = "53:45:24:64:ac:ff"
+ self.tlvs = [
+ ]
+ self.end_tlv = 0
+ self.ins = cfm.link_trace_reply(
+ self.md_lv,
+ self.version,
+ self.use_fdb_only,
+ self.fwd_yes,
+ self.terminal_mep,
+ self.transaction_id,
+ self.ttl,
+ self.relay_action,
+ self.tlvs,
+ )
+ self.form = '!4BIBBB'
+ self.buf = struct.pack(
+ self.form,
+ (self.md_lv << 5) | self.version,
+ self.opcode,
+ (self.use_fdb_only << 7) | (self.fwd_yes << 6) |
+ (self.terminal_mep << 5),
+ self.first_tlv_offset,
+ self.transaction_id,
+ self.ttl,
+ self.relay_action,
+ self.end_tlv
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.md_lv, self.ins.md_lv)
+ eq_(self.version, self.ins.version)
+ eq_(self.use_fdb_only, self.ins.use_fdb_only)
+ eq_(self.fwd_yes, self.ins.fwd_yes)
+ eq_(self.terminal_mep, self.ins.terminal_mep)
+ eq_(self.transaction_id, self.ins.transaction_id)
+ eq_(self.ttl, self.ins.ttl)
+ eq_(self.relay_action, self.ins.relay_action)
+ eq_(self.tlvs, self.ins.tlvs)
+
+ def test_parser(self):
+ _res = cfm.link_trace_reply.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.md_lv, res.md_lv)
+ eq_(self.version, res.version)
+ eq_(self.use_fdb_only, self.ins.use_fdb_only)
+ eq_(self.fwd_yes, self.ins.fwd_yes)
+ eq_(self.terminal_mep, self.ins.terminal_mep)
+ eq_(self.transaction_id, res.transaction_id)
+ eq_(self.ttl, res.ttl)
+ eq_(self.relay_action, res.relay_action)
+ eq_(self.tlvs, res.tlvs)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.md_lv, res[0] >> 5)
+ eq_(self.version, res[0] & 0x1f)
+ eq_(self.opcode, res[1])
+ eq_(self.use_fdb_only, res[2] >> 7 & 0x01)
+ eq_(self.fwd_yes, res[2] >> 6 & 0x01)
+ eq_(self.terminal_mep, res[2] >> 5 & 0x01)
+ eq_(self.first_tlv_offset, res[3])
+ eq_(self.transaction_id, res[4])
+ eq_(self.ttl, res[5])
+ eq_(self.relay_action, res[6])
+ eq_(self.end_tlv, res[7])
+
+ def test_len(self):
+ # 11 octet (If tlv does not exist)
+ eq_(11, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.link_trace_reply()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.link_trace_reply._PACK_STR, six.binary_type(buf))
+ eq_(res[0] >> 5, 0)
+ eq_(res[0] & 0x1f, 0)
+ eq_(res[1], 4)
+ eq_(res[2] >> 7, 1)
+ eq_(res[2] >> 6 & 0x01, 0)
+ eq_(res[2] >> 5 & 0x01, 1)
+ eq_(res[3], 6)
+ eq_(res[4], 0)
+ eq_(res[5], 64)
+ eq_(res[6], 1)
+
+
+class Test_sender_id_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_SENDER_ID_TLV
+ self.length = 10
+ self.chassis_id_length = 1
+ self.chassis_id_subtype = 3
+ self.chassis_id = b"\x0a"
+ self.ma_domain_length = 2
+ self.ma_domain = b"\x04\x05"
+ self.ma_length = 3
+ self.ma = b"\x01\x02\x03"
+ self.ins = cfm.sender_id_tlv(
+ self.length,
+ self.chassis_id_length,
+ self.chassis_id_subtype,
+ self.chassis_id,
+ self.ma_domain_length,
+ self.ma_domain,
+ self.ma_length,
+ self.ma,
+ )
+ self.form = '!BHBB1sB2sB3s'
+ self.buf = struct.pack(
+ self.form,
+ self._type,
+ self.length,
+ self.chassis_id_length,
+ self.chassis_id_subtype,
+ self.chassis_id,
+ self.ma_domain_length,
+ self.ma_domain,
+ self.ma_length,
+ self.ma
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.chassis_id_length, self.ins.chassis_id_length)
+ eq_(self.chassis_id_subtype, self.ins.chassis_id_subtype)
+ eq_(self.chassis_id, self.ins.chassis_id)
+ eq_(self.ma_domain_length, self.ins.ma_domain_length)
+ eq_(self.ma_domain, self.ins.ma_domain)
+ eq_(self.ma_length, self.ins.ma_length)
+ eq_(self.ma, self.ins.ma)
+
+ def test_parser(self):
+ _res = cfm.sender_id_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.chassis_id_length, res.chassis_id_length)
+ eq_(self.chassis_id_subtype, res.chassis_id_subtype)
+ eq_(self.chassis_id, res.chassis_id)
+ eq_(self.ma_domain_length, res.ma_domain_length)
+ eq_(self.ma_domain, res.ma_domain)
+ eq_(self.ma_length, res.ma_length)
+ eq_(self.ma, res.ma)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.chassis_id_length, res[2])
+ eq_(self.chassis_id_subtype, res[3])
+ eq_(self.chassis_id, res[4])
+ eq_(self.ma_domain_length, res[5])
+ eq_(self.ma_domain, res[6])
+ eq_(self.ma_length, res[7])
+ eq_(self.ma, res[8])
+
+ def test_serialize_semi_normal_ptn1(self):
+ ins = cfm.sender_id_tlv(
+ chassis_id_subtype=self.chassis_id_subtype,
+ chassis_id=self.chassis_id,
+ ma_domain=self.ma_domain,
+ )
+ buf = ins.serialize()
+ form = '!BHBB1sB2sB'
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(7, res[1])
+ eq_(self.chassis_id_length, res[2])
+ eq_(self.chassis_id_subtype, res[3])
+ eq_(self.chassis_id, res[4])
+ eq_(self.ma_domain_length, res[5])
+ eq_(self.ma_domain, res[6])
+ eq_(0, res[7])
+
+ def test_serialize_semi_normal_ptn2(self):
+ ins = cfm.sender_id_tlv(
+ ma_domain=self.ma_domain,
+ ma=self.ma,
+ )
+ buf = ins.serialize()
+ form = '!BHBB2sB3s'
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(8, res[1])
+ eq_(0, res[2])
+ eq_(self.ma_domain_length, res[3])
+ eq_(self.ma_domain, res[4])
+ eq_(self.ma_length, res[5])
+ eq_(self.ma, res[6])
+
+ def test_serialize_semi_normal_ptn3(self):
+ ins = cfm.sender_id_tlv(
+ chassis_id_subtype=self.chassis_id_subtype,
+ chassis_id=self.chassis_id,
+ )
+ buf = ins.serialize()
+ form = '!BHBB1sB'
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(4, res[1])
+ eq_(self.chassis_id_length, res[2])
+ eq_(self.chassis_id_subtype, res[3])
+ eq_(self.chassis_id, res[4])
+ eq_(0, res[5])
+
+ def test_serialize_semi_normal_ptn4(self):
+ ins = cfm.sender_id_tlv(
+ ma_domain=self.ma_domain,
+ )
+ buf = ins.serialize()
+ form = '!BHBB2sB'
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(5, res[1])
+ eq_(0, res[2])
+ eq_(self.ma_domain_length, res[3])
+ eq_(self.ma_domain, res[4])
+ eq_(0, res[5])
+
+ def test_serialize_with_length_zero(self):
+ ins = cfm.sender_id_tlv(
+ 0,
+ 0,
+ self.chassis_id_subtype,
+ self.chassis_id,
+ 0,
+ self.ma_domain,
+ 0,
+ self.ma,
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.chassis_id_length, res[2])
+ eq_(self.chassis_id_subtype, res[3])
+ eq_(self.chassis_id, res[4])
+ eq_(self.ma_domain_length, res[5])
+ eq_(self.ma_domain, res[6])
+ eq_(self.ma_length, res[7])
+ eq_(self.ma, res[8])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 10, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.sender_id_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.sender_id_tlv._PACK_STR, six.binary_type(buf))
+ eq_(res[0], cfm.CFM_SENDER_ID_TLV)
+ eq_(res[1], 1)
+ eq_(res[2], 0)
+
+
+class Test_port_status_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_PORT_STATUS_TLV
+ self.length = 1
+ self.port_status = 1
+ self.ins = cfm.port_status_tlv(
+ self.length,
+ self.port_status
+ )
+ self.form = '!BHB'
+ self.buf = struct.pack(
+ self.form,
+ self._type,
+ self.length,
+ self.port_status
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.port_status, self.ins.port_status)
+
+ def test_parser(self):
+ _res = cfm.port_status_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.port_status, res.port_status)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.port_status, res[2])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 1, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.port_status_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.port_status_tlv._PACK_STR, six.binary_type(buf))
+ eq_(res[0], cfm.CFM_PORT_STATUS_TLV)
+ eq_(res[1], 1)
+ eq_(res[2], 2)
+
+
+class Test_data_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_DATA_TLV
+ self.length = 3
+ self.data_value = b"\x01\x02\x03"
+ self.ins = cfm.data_tlv(
+ self.length,
+ self.data_value
+ )
+ self.form = '!BH3s'
+ self.buf = struct.pack(
+ self.form,
+ self._type,
+ self.length,
+ self.data_value,
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.data_value, self.ins.data_value)
+
+ def test_parser(self):
+ _res = cfm.data_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.data_value, res.data_value)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.data_value, res[2])
+
+ def test_serialize_with_length_zero(self):
+ ins = cfm.data_tlv(
+ 0,
+ self.data_value
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.data_value, res[2])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 3, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.data_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.data_tlv._PACK_STR, six.binary_type(buf))
+ eq_(res[0], cfm.CFM_DATA_TLV)
+ eq_(res[1], 0)
+
+
+class Test_interface_status_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_INTERFACE_STATUS_TLV
+ self.length = 1
+ self.interface_status = 4
+ self.ins = cfm.interface_status_tlv(
+ self.length,
+ self.interface_status
+ )
+ self.form = '!BHB'
+ self.buf = struct.pack(
+ self.form,
+ self._type,
+ self.length,
+ self.interface_status
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.interface_status, self.ins.interface_status)
+
+ def test_parser(self):
+ _res = cfm.interface_status_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.interface_status, res.interface_status)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.interface_status, res[2])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 1, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.interface_status_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.interface_status_tlv._PACK_STR, six.binary_type(buf))
+ eq_(res[0], cfm.CFM_INTERFACE_STATUS_TLV)
+ eq_(res[1], 1)
+ eq_(res[2], 1)
+
+
+class Test_ltm_egress_identifier_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_LTM_EGRESS_IDENTIFIER_TLV
+ self.length = 8
+ self.egress_id_ui = 7
+ self.egress_id_mac = "11:22:33:44:55:66"
+ self.ins = cfm.ltm_egress_identifier_tlv(
+ self.length,
+ self.egress_id_ui,
+ self.egress_id_mac
+ )
+ self.form = '!BHH6s'
+ self.buf = struct.pack(
+ self.form,
+ self._type,
+ self.length,
+ self.egress_id_ui,
+ addrconv.mac.text_to_bin(self.egress_id_mac)
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.egress_id_ui, self.ins.egress_id_ui)
+ eq_(self.egress_id_mac, self.ins.egress_id_mac)
+
+ def test_parser(self):
+ _res = cfm.ltm_egress_identifier_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.egress_id_ui, res.egress_id_ui)
+ eq_(self.egress_id_mac, res.egress_id_mac)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.egress_id_ui, res[2])
+ eq_(addrconv.mac.text_to_bin(self.egress_id_mac), res[3])
+
+ def test_serialize_with_length_zero(self):
+ ins = cfm.ltm_egress_identifier_tlv(
+ 0,
+ self.egress_id_ui,
+ self.egress_id_mac
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.egress_id_ui, res[2])
+ eq_(addrconv.mac.text_to_bin(self.egress_id_mac), res[3])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 8, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.ltm_egress_identifier_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(
+ cfm.ltm_egress_identifier_tlv._PACK_STR, six.binary_type(buf))
+ eq_(res[0], cfm.CFM_LTM_EGRESS_IDENTIFIER_TLV)
+ eq_(res[1], 8)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+
+class Test_ltr_egress_identifier_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_LTR_EGRESS_IDENTIFIER_TLV
+ self.length = 16
+ self.last_egress_id_ui = 7
+ self.last_egress_id_mac = "11:22:33:44:55:66"
+ self.next_egress_id_ui = 5
+ self.next_egress_id_mac = "33:11:33:aa:bb:cc"
+ self.ins = cfm.ltr_egress_identifier_tlv(self.length,
+ self.last_egress_id_ui,
+ self.last_egress_id_mac,
+ self.next_egress_id_ui,
+ self.next_egress_id_mac
+ )
+ self.form = '!BHH6sH6s'
+ self.buf = struct.pack(
+ self.form,
+ self._type,
+ self.length,
+ self.last_egress_id_ui,
+ addrconv.mac.text_to_bin(self.last_egress_id_mac),
+ self.next_egress_id_ui,
+ addrconv.mac.text_to_bin(self.next_egress_id_mac))
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.last_egress_id_ui, self.ins.last_egress_id_ui)
+ eq_(self.last_egress_id_mac, self.ins.last_egress_id_mac)
+ eq_(self.next_egress_id_ui, self.ins.next_egress_id_ui)
+ eq_(self.next_egress_id_mac, self.ins.next_egress_id_mac)
+
+ def test_parser(self):
+ _res = cfm.ltr_egress_identifier_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.last_egress_id_ui, res.last_egress_id_ui)
+ eq_(self.last_egress_id_mac, res.last_egress_id_mac)
+ eq_(self.next_egress_id_ui, res.next_egress_id_ui)
+ eq_(self.next_egress_id_mac, res.next_egress_id_mac)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.last_egress_id_ui, res[2])
+ eq_(addrconv.mac.text_to_bin(self.last_egress_id_mac), res[3])
+ eq_(self.next_egress_id_ui, res[4])
+ eq_(addrconv.mac.text_to_bin(self.next_egress_id_mac), res[5])
+
+ def test_serialize_with_length_zero(self):
+ ins = cfm.ltr_egress_identifier_tlv(0,
+ self.last_egress_id_ui,
+ self.last_egress_id_mac,
+ self.next_egress_id_ui,
+ self.next_egress_id_mac
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.last_egress_id_ui, res[2])
+ eq_(addrconv.mac.text_to_bin(self.last_egress_id_mac), res[3])
+ eq_(self.next_egress_id_ui, res[4])
+ eq_(addrconv.mac.text_to_bin(self.next_egress_id_mac), res[5])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 16, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.ltr_egress_identifier_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.ltr_egress_identifier_tlv._PACK_STR,
+ six.binary_type(buf))
+ eq_(res[0], cfm.CFM_LTR_EGRESS_IDENTIFIER_TLV)
+ eq_(res[1], 16)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+ eq_(res[4], 0)
+ eq_(res[5], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+
+class Test_organization_specific_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_ORGANIZATION_SPECIFIC_TLV
+ self.length = 10
+ self.oui = b"\xff\x12\x34"
+ self.subtype = 3
+ self.value = b"\x01\x02\x0f\x0e\x0d\x0c"
+ self.ins = cfm.organization_specific_tlv(self.length,
+ self.oui,
+ self.subtype,
+ self.value
+ )
+ self.form = '!BH3sB6s'
+ self.buf = struct.pack(self.form,
+ self._type,
+ self.length,
+ self.oui,
+ self.subtype,
+ self.value
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.oui, self.ins.oui)
+ eq_(self.subtype, self.ins.subtype)
+ eq_(self.value, self.ins.value)
+
+ def test_parser(self):
+ _res = cfm.organization_specific_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.oui, res.oui)
+ eq_(self.subtype, res.subtype)
+ eq_(self.value, res.value)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.oui, res[2])
+ eq_(self.subtype, res[3])
+ eq_(self.value, res[4])
+
+ def test_serialize_with_zero(self):
+ ins = cfm.organization_specific_tlv(0,
+ self.oui,
+ self.subtype,
+ self.value
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.oui, res[2])
+ eq_(self.subtype, res[3])
+ eq_(self.value, res[4])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 10, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.organization_specific_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.organization_specific_tlv._PACK_STR,
+ six.binary_type(buf))
+ eq_(res[0], cfm.CFM_ORGANIZATION_SPECIFIC_TLV)
+ eq_(res[1], 4)
+ eq_(res[2], b"\x00\x00\x00")
+ eq_(res[3], 0)
+
+
+class Test_reply_ingress_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_REPLY_INGRESS_TLV
+ self.length = 12
+ self.action = 2
+ self.mac_address = 'aa:bb:cc:56:34:12'
+ self.port_id_length = 3
+ self.port_id_subtype = 2
+ self.port_id = b"\x01\x04\x09"
+ self.ins = cfm.reply_ingress_tlv(self.length, self.action,
+ self.mac_address,
+ self.port_id_length,
+ self.port_id_subtype,
+ self.port_id
+ )
+ self.form = '!BHB6sBB3s'
+ self.buf = struct.pack(self.form,
+ self._type,
+ self.length,
+ self.action,
+ addrconv.mac.text_to_bin(self.mac_address),
+ self.port_id_length,
+ self.port_id_subtype,
+ self.port_id
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.action, self.ins.action)
+ eq_(self.mac_address, self.ins.mac_address)
+ eq_(self.port_id_length, self.ins.port_id_length)
+ eq_(self.port_id_subtype, self.ins.port_id_subtype)
+ eq_(self.port_id, self.ins.port_id)
+
+ def test_parser(self):
+ _res = cfm.reply_ingress_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.action, res.action)
+ eq_(self.mac_address, res.mac_address)
+ eq_(self.port_id_length, res.port_id_length)
+ eq_(self.port_id_subtype, res.port_id_subtype)
+ eq_(self.port_id, res.port_id)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.action, res[2])
+ eq_(addrconv.mac.text_to_bin(self.mac_address), res[3])
+ eq_(self.port_id_length, res[4])
+ eq_(self.port_id_subtype, res[5])
+ eq_(self.port_id, res[6])
+
+ def test_serialize_with_zero(self):
+ ins = cfm.reply_ingress_tlv(0,
+ self.action,
+ self.mac_address,
+ 0,
+ self.port_id_subtype,
+ self.port_id
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.action, res[2])
+ eq_(addrconv.mac.text_to_bin(self.mac_address), res[3])
+ eq_(self.port_id_length, res[4])
+ eq_(self.port_id_subtype, res[5])
+ eq_(self.port_id, res[6])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 12, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.reply_ingress_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.reply_ingress_tlv._PACK_STR, six.binary_type(buf))
+ eq_(res[0], cfm.CFM_REPLY_INGRESS_TLV)
+ eq_(res[1], 7)
+ eq_(res[2], 1)
+ eq_(res[3], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+
+class Test_reply_egress_tlv(unittest.TestCase):
+
+ def setUp(self):
+ self._type = cfm.CFM_REPLY_EGRESS_TLV
+ self.length = 12
+ self.action = 2
+ self.mac_address = 'aa:bb:cc:56:34:12'
+ self.port_id_length = 3
+ self.port_id_subtype = 2
+ self.port_id = b"\x01\x04\x09"
+ self.ins = cfm.reply_egress_tlv(self.length,
+ self.action,
+ self.mac_address,
+ self.port_id_length,
+ self.port_id_subtype,
+ self.port_id
+ )
+ self.form = '!BHB6sBB3s'
+ self.buf = struct.pack(self.form,
+ self._type,
+ self.length,
+ self.action,
+ addrconv.mac.text_to_bin(self.mac_address),
+ self.port_id_length,
+ self.port_id_subtype,
+ self.port_id
+ )
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.length, self.ins.length)
+ eq_(self.action, self.ins.action)
+ eq_(self.mac_address, self.ins.mac_address)
+ eq_(self.port_id_length, self.ins.port_id_length)
+ eq_(self.port_id_subtype, self.ins.port_id_subtype)
+ eq_(self.port_id, self.ins.port_id)
+
+ def test_parser(self):
+ _res = cfm.reply_ingress_tlv.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.length, res.length)
+ eq_(self.action, res.action)
+ eq_(self.mac_address, res.mac_address)
+ eq_(self.port_id_length, res.port_id_length)
+ eq_(self.port_id_subtype, res.port_id_subtype)
+ eq_(self.port_id, res.port_id)
+
+ def test_serialize(self):
+ buf = self.ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.action, res[2])
+ eq_(addrconv.mac.text_to_bin(self.mac_address), res[3])
+ eq_(self.port_id_length, res[4])
+ eq_(self.port_id_subtype, res[5])
+ eq_(self.port_id, res[6])
+
+ def test_serialize_with_zero(self):
+ ins = cfm.reply_egress_tlv(0,
+ self.action,
+ self.mac_address,
+ 0,
+ self.port_id_subtype,
+ self.port_id
+ )
+ buf = ins.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self._type, res[0])
+ eq_(self.length, res[1])
+ eq_(self.action, res[2])
+ eq_(addrconv.mac.text_to_bin(self.mac_address), res[3])
+ eq_(self.port_id_length, res[4])
+ eq_(self.port_id_subtype, res[5])
+ eq_(self.port_id, res[6])
+
+ def test_len(self):
+ # tlv_length = type_len + length_len + value_len
+ eq_(1 + 2 + 12, len(self.ins))
+
+ def test_default_args(self):
+ ins = cfm.reply_egress_tlv()
+ buf = ins.serialize()
+ res = struct.unpack_from(cfm.reply_egress_tlv._PACK_STR,
+ six.binary_type(buf))
+ eq_(res[0], cfm.CFM_REPLY_EGRESS_TLV)
+ eq_(res[1], 7)
+ eq_(res[2], 1)
+ eq_(res[3], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
diff --git a/tests/unit/packet/test_dhcp.py b/tests/unit/packet/test_dhcp.py
new file mode 100644
index 00000000..cc96804b
--- /dev/null
+++ b/tests/unit/packet/test_dhcp.py
@@ -0,0 +1,218 @@
+# Copyright (C) 2013 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 inspect
+import logging
+import struct
+import unittest
+
+import six
+from nose.tools import eq_
+from nose.tools import ok_
+
+from ryu.lib import addrconv
+from ryu.lib.packet import dhcp
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_dhcp_offer(unittest.TestCase):
+
+ op = dhcp.DHCP_BOOT_REPLY
+ chaddr = 'aa:aa:aa:aa:aa:aa'
+ htype = 1
+ hlen = 6
+ hops = 0
+ xid = 1
+ secs = 0
+ flags = 1
+ ciaddr = '192.168.10.10'
+ yiaddr = '192.168.20.20'
+ siaddr = '192.168.30.30'
+ giaddr = '192.168.40.40'
+ sname = 'abc'
+ boot_file = ''
+
+ option_list = [
+ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x02', 1),
+ dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, b'\xff\xff\xff\x00', 4),
+ dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, b'\xc0\xa8\x0a\x09', 4),
+ dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, b'\xc0\xa8\x0a\x09', 4),
+ dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, b'\x00\x03\xf4\x80', 4),
+ dhcp.option(dhcp.DHCP_RENEWAL_TIME_OPT, b'\x00\x01\xfa\x40', 4),
+ dhcp.option(dhcp.DHCP_REBINDING_TIME_OPT, b'\x00\x03\x75\xf0', 4),
+ dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT, b'\xc0\xa8\x0a\x09', 4)]
+ magic_cookie = '99.130.83.99'
+ options = dhcp.options(option_list=option_list, options_len=50,
+ magic_cookie=magic_cookie)
+
+ dh = dhcp.dhcp(op, chaddr, options, htype=htype, hlen=hlen,
+ hops=hops, xid=xid, secs=secs, flags=flags,
+ ciaddr=ciaddr, yiaddr=yiaddr, siaddr=siaddr,
+ giaddr=giaddr, sname=sname, boot_file=boot_file)
+
+ buf = (
+ b"\x02\x01\x06\x00\x00\x00\x00\x01\x00\x00\x00\x01\xc0\xa8\x0a\x0a"
+ b"\xc0\xa8\x14\x14\xc0\xa8\x1e\x1e\xc0\xa8\x28\x28\xaa\xaa\xaa\xaa"
+ b"\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x61\x62\x63\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63"
+ b"\x35\x01\x02\x01\x04\xff\xff\xff\x00\x03\x04\xc0\xa8\x0a\x09\x06"
+ b"\x04\xc0\xa8\x0a\x09\x33\x04\x00\x03\xf4\x80\x3a\x04\x00\x01\xfa"
+ b"\x40\x3b\x04\x00\x03\x75\xf0\x36\x04\xc0\xa8\x0a\x09\xff")
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.op, self.dh.op)
+ eq_(self.htype, self.dh.htype)
+ eq_(self.hlen, self.dh.hlen)
+ eq_(self.hops, self.dh.hops)
+ eq_(self.xid, self.dh.xid)
+ eq_(self.secs, self.dh.secs)
+ eq_(self.flags, self.dh.flags)
+ eq_(self.ciaddr, self.dh.ciaddr)
+ eq_(self.yiaddr, self.dh.yiaddr)
+ eq_(self.siaddr, self.dh.siaddr)
+ eq_(self.giaddr, self.dh.giaddr)
+ eq_(self.chaddr, self.dh.chaddr)
+ eq_(self.sname, self.dh.sname)
+ eq_(self.boot_file, self.dh.boot_file)
+ eq_(str(self.options), str(self.dh.options))
+
+ def test_parser(self):
+ res, _, rest = dhcp.dhcp.parser(self.buf)
+
+ eq_(self.op, res.op)
+ eq_(self.htype, res.htype)
+ eq_(self.hlen, res.hlen)
+ eq_(self.hops, res.hops)
+ eq_(self.xid, res.xid)
+ eq_(self.secs, res.secs)
+ eq_(self.flags, res.flags)
+ eq_(self.ciaddr, res.ciaddr)
+ eq_(self.yiaddr, res.yiaddr)
+ eq_(self.siaddr, res.siaddr)
+ eq_(self.giaddr, res.giaddr)
+ eq_(self.chaddr, res.chaddr)
+ # sname is 64 byte length. rest of data is filled by '\x00'.
+ eq_(self.sname.ljust(64, '\x00'), res.sname)
+ # boof_file is 128 byte length. rest of data is filled by '\x00'.
+ eq_(self.boot_file.ljust(128, '\x00'), res.boot_file)
+ eq_(str(self.options), str(res.options))
+ eq_(b'', rest)
+
+ def test_parser_corrupted(self):
+ corrupt_buf = self.buf[:-4]
+ pkt, _, rest = dhcp.dhcp.parser(corrupt_buf)
+
+ ok_(isinstance(pkt, dhcp.dhcp))
+ ok_(isinstance(pkt.options, dhcp.options))
+ for opt in pkt.options.option_list[:-1]:
+ ok_(isinstance(opt, dhcp.option))
+ ok_(isinstance(pkt.options.option_list[-1], six.binary_type))
+
+ buf = pkt.serialize()
+ eq_(str(buf), str(corrupt_buf))
+ eq_(b'', rest)
+
+ def test_serialize(self):
+ buf = self.dh.serialize()
+
+ res = struct.unpack_from(dhcp.dhcp._DHCP_PACK_STR,
+ six.binary_type(buf))
+
+ eq_(self.op, res[0])
+ eq_(self.htype, res[1])
+ eq_(self.hlen, res[2])
+ eq_(self.hops, res[3])
+ eq_(self.xid, res[4])
+ eq_(self.secs, res[5])
+ eq_(self.flags, res[6])
+ eq_(self.ciaddr, addrconv.ipv4.bin_to_text(res[7]))
+ eq_(self.yiaddr, addrconv.ipv4.bin_to_text(res[8]))
+ eq_(self.siaddr, addrconv.ipv4.bin_to_text(res[9]))
+ eq_(self.giaddr, addrconv.ipv4.bin_to_text(res[10]))
+ eq_(self.chaddr, addrconv.mac.bin_to_text(res[11][:6]))
+ # sname is 64 byte length. rest of data is filled by '\x00'.
+ eq_(self.sname.ljust(64, '\x00'), res[12].decode('ascii'))
+ # boof_file is 128 byte length. rest of data is filled by '\x00'.
+ eq_(self.boot_file.ljust(128, '\x00'), res[13].decode('ascii'))
+ options = dhcp.options.parser(
+ buf[struct.calcsize(dhcp.dhcp._DHCP_PACK_STR):])
+ eq_(str(self.options), str(options))
+
+ def test_to_string(self):
+ option_values = ['tag', 'length', 'value']
+ opt_str_list = []
+ for option in self.option_list:
+ _opt_str = ','.join(['%s=%s' % (k, repr(getattr(option, k)))
+ for k, v in inspect.getmembers(option)
+ if k in option_values])
+ opt_str = '%s(%s)' % (dhcp.option.__name__, _opt_str)
+ opt_str_list.append(opt_str)
+ option_str = '[%s]' % ', '.join(opt_str_list)
+
+ opts_vals = {'magic_cookie': repr(self.magic_cookie),
+ 'option_list': option_str,
+ 'options_len': repr(self.options.options_len)}
+ _options_str = ','.join(['%s=%s' % (k, opts_vals[k])
+ for k, v in inspect.getmembers(self.options)
+ if k in opts_vals])
+ options_str = '%s(%s)' % (dhcp.options.__name__, _options_str)
+
+ dhcp_values = {'op': repr(self.op),
+ 'htype': repr(self.htype),
+ 'hlen': repr(self.hlen),
+ 'hops': repr(self.hops),
+ 'xid': repr(self.xid),
+ 'secs': repr(self.secs),
+ 'flags': repr(self.flags),
+ 'ciaddr': repr(self.ciaddr),
+ 'yiaddr': repr(self.yiaddr),
+ 'siaddr': repr(self.siaddr),
+ 'giaddr': repr(self.giaddr),
+ 'chaddr': repr(self.chaddr),
+ 'sname': repr(self.sname),
+ 'boot_file': repr(self.boot_file),
+ 'options': options_str}
+ _dh_str = ','.join(['%s=%s' % (k, dhcp_values[k])
+ for k, v in inspect.getmembers(self.dh)
+ if k in dhcp_values])
+ dh_str = '%s(%s)' % (dhcp.dhcp.__name__, _dh_str)
+
+ eq_(str(self.dh), dh_str)
+ eq_(repr(self.dh), dh_str)
+
+ def test_json(self):
+ jsondict = self.dh.to_jsondict()
+ dh = dhcp.dhcp.from_jsondict(jsondict['dhcp'])
+ eq_(str(self.dh), str(dh))
diff --git a/tests/unit/packet/test_ethernet.py b/tests/unit/packet/test_ethernet.py
new file mode 100644
index 00000000..6fd767bd
--- /dev/null
+++ b/tests/unit/packet/test_ethernet.py
@@ -0,0 +1,103 @@
+# 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 unittest
+import logging
+import six
+import struct
+import netaddr
+from struct import *
+from nose.tools import *
+from ryu.ofproto import ether, inet
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet.arp import arp
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger('test_ethernet')
+
+
+class Test_ethernet(unittest.TestCase):
+ """ Test case for ethernet
+ """
+
+ dst = 'aa:aa:aa:aa:aa:aa'
+ src = 'bb:bb:bb:bb:bb:bb'
+ ethertype = ether.ETH_TYPE_ARP
+
+ buf = pack(ethernet._PACK_STR,
+ addrconv.mac.text_to_bin(dst),
+ addrconv.mac.text_to_bin(src), ethertype)
+
+ e = ethernet(dst, src, ethertype)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.dst, self.e.dst)
+ eq_(self.src, self.e.src)
+ eq_(self.ethertype, self.e.ethertype)
+
+ def test_parser(self):
+ res, ptype, _ = self.e.parser(self.buf)
+ LOG.debug((res, ptype))
+
+ eq_(res.dst, self.dst)
+ eq_(res.src, self.src)
+ eq_(res.ethertype, self.ethertype)
+ eq_(ptype, arp)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.e.serialize(data, prev)
+
+ fmt = ethernet._PACK_STR
+ res = struct.unpack(fmt, buf)
+
+ eq_(res[0], addrconv.mac.text_to_bin(self.dst))
+ eq_(res[1], addrconv.mac.text_to_bin(self.src))
+ eq_(res[2], self.ethertype)
+
+ @raises(Exception)
+ def test_malformed_ethernet(self):
+ m_short_buf = self.buf[1:ethernet._MIN_LEN]
+ ethernet.parser(m_short_buf)
+
+ def test_default_args(self):
+ e = ethernet()
+ buf = e.serialize(bytearray(), None)
+ res = struct.unpack(e._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], addrconv.mac.text_to_bin('ff:ff:ff:ff:ff:ff'))
+ eq_(res[1], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+ eq_(res[2], ether.ETH_TYPE_IP)
+
+ def test_json(self):
+ jsondict = self.e.to_jsondict()
+ e = ethernet.from_jsondict(jsondict['ethernet'])
+ eq_(str(self.e), str(e))
diff --git a/tests/unit/packet/test_geneve.py b/tests/unit/packet/test_geneve.py
new file mode 100644
index 00000000..919d05f8
--- /dev/null
+++ b/tests/unit/packet/test_geneve.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2016 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.
+
+from __future__ import print_function
+
+import logging
+import os
+import sys
+
+import unittest
+from nose.tools import eq_
+from nose.tools import ok_
+
+from ryu.lib import pcaplib
+from ryu.lib.packet import geneve
+from ryu.lib.packet import packet
+from ryu.utils import binary_str
+
+
+LOG = logging.getLogger(__name__)
+
+GENEVE_DATA_DIR = os.path.join(
+ os.path.dirname(sys.modules[__name__].__file__),
+ '../../packet_data/pcap/')
+
+
+class Test_geneve(unittest.TestCase):
+ """
+ Test case for ryu.lib.packet.geneve.
+ """
+
+ def test_parser(self):
+ files = [
+ 'geneve_unknown',
+ ]
+
+ for f in files:
+ # print('*** testing %s ...' % f)
+ for _, buf in pcaplib.Reader(
+ open(GENEVE_DATA_DIR + f + '.pcap', 'rb')):
+ # Checks if message can be parsed as expected.
+ pkt = packet.Packet(buf)
+ geneve_pkt = pkt.get_protocol(geneve.geneve)
+ ok_(isinstance(geneve_pkt, geneve.geneve),
+ 'Failed to parse Geneve message: %s' % pkt)
+
+ # Checks if message can be serialized as expected.
+ pkt.serialize()
+ eq_(buf, pkt.data,
+ "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))
diff --git a/tests/unit/packet/test_gre.py b/tests/unit/packet/test_gre.py
new file mode 100644
index 00000000..c955ec70
--- /dev/null
+++ b/tests/unit/packet/test_gre.py
@@ -0,0 +1,115 @@
+# Copyright (C) 2016 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.
+
+from __future__ import print_function
+
+import logging
+import os
+import sys
+
+import unittest
+from nose.tools import eq_
+from nose.tools import ok_
+
+from ryu.lib import pcaplib
+from ryu.lib.packet import gre
+from ryu.lib.packet import packet
+from ryu.utils import binary_str
+from ryu.lib.packet.ether_types import ETH_TYPE_IP, ETH_TYPE_TEB
+
+LOG = logging.getLogger(__name__)
+
+GENEVE_DATA_DIR = os.path.join(
+ os.path.dirname(sys.modules[__name__].__file__),
+ '../../packet_data/pcap/')
+
+
+class Test_gre(unittest.TestCase):
+ """
+ Test case gre for ryu.lib.packet.gre.
+ """
+
+ version = 0
+ gre_proto = ETH_TYPE_IP
+ nvgre_proto = ETH_TYPE_TEB
+ checksum = 0x440d
+ seq_number = 10
+ key = 256100
+ vsid = 1000
+ flow_id = 100
+
+ gre = gre.gre(version=version, protocol=gre_proto, checksum=checksum,
+ key=key, seq_number=seq_number)
+
+ def test_key_setter(self):
+ self.gre.key = self.key
+ eq_(self.gre._key, self.key)
+ eq_(self.gre._vsid, self.vsid)
+ eq_(self.gre._flow_id, self.flow_id)
+
+ def test_key_setter_none(self):
+ self.gre.key = None
+ eq_(self.gre._key, None)
+ eq_(self.gre._vsid, None)
+ eq_(self.gre._flow_id, None)
+
+ self.gre.key = self.key
+
+ def test_vsid_setter(self):
+ self.gre.vsid = self.vsid
+ eq_(self.gre._key, self.key)
+ eq_(self.gre._vsid, self.vsid)
+ eq_(self.gre._flow_id, self.flow_id)
+
+ def test_flowid_setter(self):
+ self.gre.flow_id = self.flow_id
+ eq_(self.gre._key, self.key)
+ eq_(self.gre._vsid, self.vsid)
+ eq_(self.gre._flow_id, self.flow_id)
+
+ def test_nvgre_init(self):
+ nvgre = gre.nvgre(version=self.version, vsid=self.vsid,
+ flow_id=self.flow_id)
+
+ eq_(nvgre.version, self.version)
+ eq_(nvgre.protocol, self.nvgre_proto)
+ eq_(nvgre.checksum, None)
+ eq_(nvgre.seq_number, None)
+ eq_(nvgre._key, self.key)
+ eq_(nvgre._vsid, self.vsid)
+ eq_(nvgre._flow_id, self.flow_id)
+
+ def test_parser(self):
+ files = [
+ 'gre_full_options',
+ 'gre_no_option',
+ 'gre_nvgre_option',
+ ]
+
+ for f in files:
+ # print('*** testing %s ...' % f)
+ for _, buf in pcaplib.Reader(
+ open(GENEVE_DATA_DIR + f + '.pcap', 'rb')):
+ # Checks if message can be parsed as expected.
+ pkt = packet.Packet(buf)
+ gre_pkt = pkt.get_protocol(gre.gre)
+ ok_(isinstance(gre_pkt, gre.gre),
+ 'Failed to parse Gre message: %s' % pkt)
+
+ # Checks if message can be serialized as expected.
+ pkt.serialize()
+
+ eq_(buf, pkt.data,
+ "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))
diff --git a/tests/unit/packet/test_icmp.py b/tests/unit/packet/test_icmp.py
new file mode 100644
index 00000000..f9438893
--- /dev/null
+++ b/tests/unit/packet/test_icmp.py
@@ -0,0 +1,380 @@
+# Copyright (C) 2013 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 inspect
+import logging
+import six
+import struct
+import unittest
+
+from nose.tools import eq_
+from ryu.lib.packet import icmp
+from ryu.lib.packet import packet_utils
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_icmp(unittest.TestCase):
+
+ echo_id = None
+ echo_seq = None
+ echo_data = None
+
+ unreach_mtu = None
+ unreach_data = None
+ unreach_data_len = None
+
+ te_data = None
+ te_data_len = None
+
+ def setUp(self):
+ self.type_ = icmp.ICMP_ECHO_REQUEST
+ self.code = 0
+ self.csum = 0
+ self.data = None
+
+ self.ic = icmp.icmp(self.type_, self.code, self.csum, self.data)
+
+ self.buf = bytearray(struct.pack(
+ icmp.icmp._PACK_STR, self.type_, self.code, self.csum))
+ self.csum_calc = packet_utils.checksum(self.buf)
+ struct.pack_into('!H', self.buf, 2, self.csum_calc)
+
+ def setUp_with_echo(self):
+ self.echo_id = 13379
+ self.echo_seq = 1
+ self.echo_data = b'\x30\x0e\x09\x00\x00\x00\x00\x00' \
+ + b'\x10\x11\x12\x13\x14\x15\x16\x17' \
+ + b'\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' \
+ + b'\x20\x21\x22\x23\x24\x25\x26\x27' \
+ + b'\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f' \
+ + b'\x30\x31\x32\x33\x34\x35\x36\x37'
+ self.data = icmp.echo(
+ id_=self.echo_id, seq=self.echo_seq, data=self.echo_data)
+
+ self.type_ = icmp.ICMP_ECHO_REQUEST
+ self.code = 0
+ self.ic = icmp.icmp(self.type_, self.code, self.csum, self.data)
+
+ self.buf = bytearray(struct.pack(
+ icmp.icmp._PACK_STR, self.type_, self.code, self.csum))
+ self.buf += self.data.serialize()
+ self.csum_calc = packet_utils.checksum(self.buf)
+ struct.pack_into('!H', self.buf, 2, self.csum_calc)
+
+ def setUp_with_dest_unreach(self):
+ self.unreach_mtu = 10
+ self.unreach_data = b'abc'
+ self.unreach_data_len = len(self.unreach_data)
+ self.data = icmp.dest_unreach(
+ data_len=self.unreach_data_len, mtu=self.unreach_mtu,
+ data=self.unreach_data)
+
+ self.type_ = icmp.ICMP_DEST_UNREACH
+ self.code = icmp.ICMP_HOST_UNREACH_CODE
+ self.ic = icmp.icmp(self.type_, self.code, self.csum, self.data)
+
+ self.buf = bytearray(struct.pack(
+ icmp.icmp._PACK_STR, self.type_, self.code, self.csum))
+ self.buf += self.data.serialize()
+ self.csum_calc = packet_utils.checksum(self.buf)
+ struct.pack_into('!H', self.buf, 2, self.csum_calc)
+
+ def setUp_with_TimeExceeded(self):
+ self.te_data = b'abc'
+ self.te_data_len = len(self.te_data)
+ self.data = icmp.TimeExceeded(
+ data_len=self.te_data_len, data=self.te_data)
+
+ self.type_ = icmp.ICMP_TIME_EXCEEDED
+ self.code = 0
+ self.ic = icmp.icmp(self.type_, self.code, self.csum, self.data)
+
+ self.buf = bytearray(struct.pack(
+ icmp.icmp._PACK_STR, self.type_, self.code, self.csum))
+ self.buf += self.data.serialize()
+ self.csum_calc = packet_utils.checksum(self.buf)
+ struct.pack_into('!H', self.buf, 2, self.csum_calc)
+
+ def test_init(self):
+ eq_(self.type_, self.ic.type)
+ eq_(self.code, self.ic.code)
+ eq_(self.csum, self.ic.csum)
+ eq_(str(self.data), str(self.ic.data))
+
+ def test_init_with_echo(self):
+ self.setUp_with_echo()
+ self.test_init()
+
+ def test_init_with_dest_unreach(self):
+ self.setUp_with_dest_unreach()
+ self.test_init()
+
+ def test_init_with_TimeExceeded(self):
+ self.setUp_with_TimeExceeded()
+ self.test_init()
+
+ def test_parser(self):
+ _res = icmp.icmp.parser(six.binary_type(self.buf))
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(self.type_, res.type)
+ eq_(self.code, res.code)
+ eq_(self.csum_calc, res.csum)
+ eq_(str(self.data), str(res.data))
+
+ def test_parser_with_echo(self):
+ self.setUp_with_echo()
+ self.test_parser()
+
+ def test_parser_with_dest_unreach(self):
+ self.setUp_with_dest_unreach()
+ self.test_parser()
+
+ def test_parser_with_TimeExceeded(self):
+ self.setUp_with_TimeExceeded()
+ self.test_parser()
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.ic.serialize(data, prev)
+
+ res = struct.unpack_from(icmp.icmp._PACK_STR, six.binary_type(buf))
+
+ eq_(self.type_, res[0])
+ eq_(self.code, res[1])
+ eq_(self.csum_calc, res[2])
+
+ def test_serialize_with_echo(self):
+ self.setUp_with_echo()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ic.serialize(data, prev)
+ echo = icmp.echo.parser(six.binary_type(buf), icmp.icmp._MIN_LEN)
+ eq_(repr(self.data), repr(echo))
+
+ def test_serialize_with_dest_unreach(self):
+ self.setUp_with_dest_unreach()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ic.serialize(data, prev)
+ unreach = icmp.dest_unreach.parser(six.binary_type(buf), icmp.icmp._MIN_LEN)
+ eq_(repr(self.data), repr(unreach))
+
+ def test_serialize_with_TimeExceeded(self):
+ self.setUp_with_TimeExceeded()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ic.serialize(data, prev)
+ te = icmp.TimeExceeded.parser(six.binary_type(buf), icmp.icmp._MIN_LEN)
+ eq_(repr(self.data), repr(te))
+
+ def test_to_string(self):
+ icmp_values = {'type': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': repr(self.data)}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(self.ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmp.icmp.__name__, _ic_str)
+
+ eq_(str(self.ic), ic_str)
+ eq_(repr(self.ic), ic_str)
+
+ def test_to_string_with_echo(self):
+ self.setUp_with_echo()
+ self.test_to_string()
+
+ def test_to_string_with_dest_unreach(self):
+ self.setUp_with_dest_unreach()
+ self.test_to_string()
+
+ def test_to_string_with_TimeExceeded(self):
+ self.setUp_with_TimeExceeded()
+ self.test_to_string()
+
+ def test_default_args(self):
+ ic = icmp.icmp()
+ buf = ic.serialize(bytearray(), None)
+ res = struct.unpack(icmp.icmp._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], 8)
+ eq_(res[1], 0)
+ eq_(buf[4:], b'\x00\x00\x00\x00')
+
+ # with data
+ ic = icmp.icmp(type_=icmp.ICMP_DEST_UNREACH, data=icmp.dest_unreach())
+ buf = ic.serialize(bytearray(), None)
+ res = struct.unpack(icmp.icmp._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], 3)
+ eq_(res[1], 0)
+ eq_(buf[4:], b'\x00\x00\x00\x00')
+
+ def test_json(self):
+ jsondict = self.ic.to_jsondict()
+ ic = icmp.icmp.from_jsondict(jsondict['icmp'])
+ eq_(str(self.ic), str(ic))
+
+ def test_json_with_echo(self):
+ self.setUp_with_echo()
+ self.test_json()
+
+ def test_json_with_dest_unreach(self):
+ self.setUp_with_dest_unreach()
+ self.test_json()
+
+ def test_json_with_TimeExceeded(self):
+ self.setUp_with_TimeExceeded()
+ self.test_json()
+
+
+class Test_echo(unittest.TestCase):
+
+ def setUp(self):
+ self.id_ = 13379
+ self.seq = 1
+ self.data = b'\x30\x0e\x09\x00\x00\x00\x00\x00' \
+ + b'\x10\x11\x12\x13\x14\x15\x16\x17' \
+ + b'\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' \
+ + b'\x20\x21\x22\x23\x24\x25\x26\x27' \
+ + b'\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f' \
+ + b'\x30\x31\x32\x33\x34\x35\x36\x37'
+ self.echo = icmp.echo(
+ self.id_, self.seq, self.data)
+ self.buf = struct.pack('!HH', self.id_, self.seq)
+ self.buf += self.data
+
+ def test_init(self):
+ eq_(self.id_, self.echo.id)
+ eq_(self.seq, self.echo.seq)
+ eq_(self.data, self.echo.data)
+
+ def test_parser(self):
+ _res = icmp.echo.parser(self.buf, 0)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.id_, res.id)
+ eq_(self.seq, res.seq)
+ eq_(self.data, res.data)
+
+ def test_serialize(self):
+ buf = self.echo.serialize()
+ res = struct.unpack_from('!HH', six.binary_type(buf))
+ eq_(self.id_, res[0])
+ eq_(self.seq, res[1])
+ eq_(self.data, buf[struct.calcsize('!HH'):])
+
+ def test_default_args(self):
+ ec = icmp.echo()
+ buf = ec.serialize()
+ res = struct.unpack(icmp.echo._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+
+
+class Test_dest_unreach(unittest.TestCase):
+
+ def setUp(self):
+ self.mtu = 10
+ self.data = b'abc'
+ self.data_len = len(self.data)
+ self.dest_unreach = icmp.dest_unreach(
+ data_len=self.data_len, mtu=self.mtu, data=self.data)
+ self.buf = struct.pack('!xBH', self.data_len, self.mtu)
+ self.buf += self.data
+
+ def test_init(self):
+ eq_(self.data_len, self.dest_unreach.data_len)
+ eq_(self.mtu, self.dest_unreach.mtu)
+ eq_(self.data, self.dest_unreach.data)
+
+ def test_parser(self):
+ _res = icmp.dest_unreach.parser(self.buf, 0)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.data_len, res.data_len)
+ eq_(self.mtu, res.mtu)
+ eq_(self.data, res.data)
+
+ def test_serialize(self):
+ buf = self.dest_unreach.serialize()
+ res = struct.unpack_from('!xBH', six.binary_type(buf))
+ eq_(self.data_len, res[0])
+ eq_(self.mtu, res[1])
+ eq_(self.data, buf[struct.calcsize('!xBH'):])
+
+ def test_default_args(self):
+ du = icmp.dest_unreach()
+ buf = du.serialize()
+ res = struct.unpack(icmp.dest_unreach._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+
+
+class Test_TimeExceeded(unittest.TestCase):
+
+ def setUp(self):
+ self.data = b'abc'
+ self.data_len = len(self.data)
+ self.te = icmp.TimeExceeded(
+ data_len=self.data_len, data=self.data)
+ self.buf = struct.pack('!xBxx', self.data_len)
+ self.buf += self.data
+
+ def test_init(self):
+ eq_(self.data_len, self.te.data_len)
+ eq_(self.data, self.te.data)
+
+ def test_parser(self):
+ _res = icmp.TimeExceeded.parser(self.buf, 0)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.data_len, res.data_len)
+ eq_(self.data, res.data)
+
+ def test_serialize(self):
+ buf = self.te.serialize()
+ res = struct.unpack_from('!xBxx', six.binary_type(buf))
+ eq_(self.data_len, res[0])
+ eq_(self.data, buf[struct.calcsize('!xBxx'):])
+
+ def test_default_args(self):
+ te = icmp.TimeExceeded()
+ buf = te.serialize()
+ res = struct.unpack(icmp.TimeExceeded._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
diff --git a/tests/unit/packet/test_icmpv6.py b/tests/unit/packet/test_icmpv6.py
new file mode 100644
index 00000000..c6438171
--- /dev/null
+++ b/tests/unit/packet/test_icmpv6.py
@@ -0,0 +1,2039 @@
+# 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 unittest
+import logging
+import six
+import struct
+import inspect
+
+from nose.tools import ok_, eq_, nottest, raises
+from ryu.ofproto import ether, inet
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet import icmpv6
+from ryu.lib.packet.ipv6 import ipv6
+from ryu.lib.packet import packet_utils
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger(__name__)
+
+
+def icmpv6_csum(prev, buf):
+ ph = struct.pack('!16s16sI3xB',
+ addrconv.ipv6.text_to_bin(prev.src),
+ addrconv.ipv6.text_to_bin(prev.dst),
+ prev.payload_length, prev.nxt)
+ h = bytearray(buf)
+ struct.pack_into('!H', h, 2, 0)
+
+ return packet_utils.checksum(ph + h)
+
+
+class Test_icmpv6_header(unittest.TestCase):
+ type_ = 255
+ code = 0
+ csum = 207
+ buf = b'\xff\x00\x00\xcf'
+ icmp = icmpv6.icmpv6(type_, code, 0)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.type_, self.icmp.type_)
+ eq_(self.code, self.icmp.code)
+ eq_(0, self.icmp.csum)
+
+ def test_parser(self):
+ msg, n, _ = self.icmp.parser(self.buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ eq_(msg.data, None)
+ eq_(n, None)
+
+ def test_serialize(self):
+ src_ipv6 = 'fe80::200:ff:fe00:ef'
+ dst_ipv6 = 'fe80::200:ff:fe00:1'
+ prev = ipv6(6, 0, 0, 4, 58, 255, src_ipv6, dst_ipv6)
+
+ buf = self.icmp.serialize(bytearray(), prev)
+ (type_, code, csum) = struct.unpack(self.icmp._PACK_STR, six.binary_type(buf))
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, self.csum)
+
+ @raises(Exception)
+ def test_malformed_icmpv6(self):
+ m_short_buf = self.buf[1:self.icmp._MIN_LEN]
+ self.icmp.parser(m_short_buf)
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6()
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ def test_json(self):
+ jsondict = self.icmp.to_jsondict()
+ icmp = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(self.icmp), str(icmp))
+
+
+class Test_icmpv6_echo_request(unittest.TestCase):
+ type_ = 128
+ code = 0
+ csum = 0xa572
+ id_ = 0x7620
+ seq = 0
+ data = b'\x01\xc9\xe7\x36\xd3\x39\x06\x00'
+ buf = b'\x80\x00\xa5\x72\x76\x20\x00\x00'
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ echo = icmpv6.echo(0, 0)
+ eq_(echo.id, 0)
+ eq_(echo.seq, 0)
+ eq_(echo.data, None)
+
+ def _test_parser(self, data=None):
+ buf = self.buf + (data or b'')
+ msg, n, _ = icmpv6.icmpv6.parser(buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ eq_(msg.data.id, self.id_)
+ eq_(msg.data.seq, self.seq)
+ eq_(msg.data.data, data)
+ eq_(n, None)
+
+ def test_parser_without_data(self):
+ self._test_parser()
+
+ def test_parser_with_data(self):
+ self._test_parser(self.data)
+
+ def _test_serialize(self, echo_data=None):
+ buf = self.buf + (echo_data or b'')
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+ prev = ipv6(6, 0, 0, len(buf), 64, 255, src_ipv6, dst_ipv6)
+ echo_csum = icmpv6_csum(prev, buf)
+
+ echo = icmpv6.echo(self.id_, self.seq, echo_data)
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, echo)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ (id_, seq) = struct.unpack_from(echo._PACK_STR, buf, icmp._MIN_LEN)
+ data = buf[(icmp._MIN_LEN + echo._MIN_LEN):]
+ data = data if len(data) != 0 else None
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, echo_csum)
+ eq_(id_, self.id_)
+ eq_(seq, self.seq)
+ eq_(data, echo_data)
+
+ def test_serialize_without_data(self):
+ self._test_serialize()
+
+ def test_serialize_with_data(self):
+ self._test_serialize(self.data)
+
+ def test_to_string(self):
+ ec = icmpv6.echo(self.id_, self.seq, self.data)
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, ec)
+
+ echo_values = {'id': self.id_,
+ 'seq': self.seq,
+ 'data': self.data}
+ _echo_str = ','.join(['%s=%s' % (k, repr(echo_values[k]))
+ for k, v in inspect.getmembers(ec)
+ if k in echo_values])
+ echo_str = '%s(%s)' % (icmpv6.echo.__name__, _echo_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': echo_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ICMPV6_ECHO_REQUEST, data=icmpv6.echo())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ICMPV6_ECHO_REQUEST)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.echo._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+
+ def test_json(self):
+ ec = icmpv6.echo(self.id_, self.seq, self.data)
+ ic1 = icmpv6.icmpv6(self.type_, self.code, self.csum, ec)
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_icmpv6_echo_reply(Test_icmpv6_echo_request):
+ def setUp(self):
+ self.type_ = 129
+ self.csum = 0xa472
+ self.buf = b'\x81\x00\xa4\x72\x76\x20\x00\x00'
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ICMPV6_ECHO_REPLY)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.echo._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+
+
+class Test_icmpv6_neighbor_solicit(unittest.TestCase):
+ type_ = 135
+ code = 0
+ csum = 0x952d
+ res = 0
+ dst = '3ffe:507:0:1:200:86ff:fe05:80da'
+ nd_type = 1
+ nd_length = 1
+ nd_hw_src = '00:60:97:07:69:ea'
+ data = b'\x01\x01\x00\x60\x97\x07\x69\xea'
+ buf = b'\x87\x00\x95\x2d\x00\x00\x00\x00' \
+ + b'\x3f\xfe\x05\x07\x00\x00\x00\x01' \
+ + b'\x02\x00\x86\xff\xfe\x05\x80\xda'
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ nd = icmpv6.nd_neighbor(self.res, self.dst)
+ eq_(nd.res, self.res)
+ eq_(nd.dst, self.dst)
+ eq_(nd.option, None)
+
+ def _test_parser(self, data=None):
+ buf = self.buf + (data or b'')
+ msg, n, _ = icmpv6.icmpv6.parser(buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ eq_(msg.data.res, self.res)
+ eq_(addrconv.ipv6.text_to_bin(msg.data.dst),
+ addrconv.ipv6.text_to_bin(self.dst))
+ eq_(n, None)
+ if data:
+ nd = msg.data.option
+ eq_(nd.length, self.nd_length)
+ eq_(nd.hw_src, self.nd_hw_src)
+ eq_(nd.data, None)
+
+ def test_parser_without_data(self):
+ self._test_parser()
+
+ def test_parser_with_data(self):
+ self._test_parser(self.data)
+
+ def test_serialize_without_data(self):
+ nd = icmpv6.nd_neighbor(self.res, self.dst)
+ prev = ipv6(6, 0, 0, 24, 64, 255, self.src_ipv6, self.dst_ipv6)
+ nd_csum = icmpv6_csum(prev, self.buf)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, nd)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ (res, dst) = struct.unpack_from(nd._PACK_STR, buf, icmp._MIN_LEN)
+ data = buf[(icmp._MIN_LEN + nd._MIN_LEN):]
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, nd_csum)
+ eq_(res >> 29, self.res)
+ eq_(dst, addrconv.ipv6.text_to_bin(self.dst))
+ eq_(data, b'')
+
+ def test_serialize_with_data(self):
+ nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src)
+ nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt)
+ prev = ipv6(6, 0, 0, 32, 64, 255, self.src_ipv6, self.dst_ipv6)
+ nd_csum = icmpv6_csum(prev, self.buf + self.data)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, nd)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ (res, dst) = struct.unpack_from(nd._PACK_STR, buf, icmp._MIN_LEN)
+ (nd_type, nd_length, nd_hw_src) = struct.unpack_from(
+ nd_opt._PACK_STR, buf, icmp._MIN_LEN + nd._MIN_LEN)
+ data = buf[(icmp._MIN_LEN + nd._MIN_LEN + 8):]
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, nd_csum)
+ eq_(res >> 29, self.res)
+ eq_(dst, addrconv.ipv6.text_to_bin(self.dst))
+ eq_(nd_type, self.nd_type)
+ eq_(nd_length, self.nd_length)
+ eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
+
+ def test_to_string(self):
+ nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src)
+ nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt)
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, nd)
+
+ nd_opt_values = {'length': self.nd_length,
+ 'hw_src': self.nd_hw_src,
+ 'data': None}
+ _nd_opt_str = ','.join(['%s=%s' % (k, repr(nd_opt_values[k]))
+ for k, v in inspect.getmembers(nd_opt)
+ if k in nd_opt_values])
+ nd_opt_str = '%s(%s)' % (icmpv6.nd_option_sla.__name__, _nd_opt_str)
+
+ nd_values = {'res': repr(nd.res),
+ 'dst': repr(self.dst),
+ 'option': nd_opt_str}
+ _nd_str = ','.join(['%s=%s' % (k, nd_values[k])
+ for k, v in inspect.getmembers(nd)
+ if k in nd_values])
+ nd_str = '%s(%s)' % (icmpv6.nd_neighbor.__name__, _nd_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': nd_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_NEIGHBOR_SOLICIT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+
+ # with nd_option_sla
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_NEIGHBOR_SOLICIT,
+ data=icmpv6.nd_neighbor(
+ option=icmpv6.nd_option_sla()))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_NEIGHBOR_SOLICIT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_neighbor._PACK_STR,
+ six.binary_type(buf[4:24]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+
+ res = struct.unpack(icmpv6.nd_option_sla._PACK_STR,
+ six.binary_type(buf[24:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_SLA)
+ eq_(res[1], len(icmpv6.nd_option_sla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+ def test_json(self):
+ nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src)
+ nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt)
+ ic1 = icmpv6.icmpv6(self.type_, self.code, self.csum, nd)
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_icmpv6_neighbor_advert(Test_icmpv6_neighbor_solicit):
+ def setUp(self):
+ self.type_ = 136
+ self.csum = 0xb8ba
+ self.res = 7
+ self.dst = '3ffe:507:0:1:260:97ff:fe07:69ea'
+ self.nd_type = 2
+ self.nd_length = 1
+ self.nd_data = None
+ self.nd_hw_src = '00:60:97:07:69:ea'
+ self.data = b'\x02\x01\x00\x60\x97\x07\x69\xea'
+ self.buf = b'\x88\x00\xb8\xba\xe0\x00\x00\x00' \
+ + b'\x3f\xfe\x05\x07\x00\x00\x00\x01' \
+ + b'\x02\x60\x97\xff\xfe\x07\x69\xea'
+
+ def test_serialize_with_data(self):
+ nd_opt = icmpv6.nd_option_tla(self.nd_length, self.nd_hw_src)
+ nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt)
+ prev = ipv6(6, 0, 0, 32, 64, 255, self.src_ipv6, self.dst_ipv6)
+ nd_csum = icmpv6_csum(prev, self.buf + self.data)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, nd)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ (res, dst) = struct.unpack_from(nd._PACK_STR, buf, icmp._MIN_LEN)
+ (nd_type, nd_length, nd_hw_src) = struct.unpack_from(
+ nd_opt._PACK_STR, buf, icmp._MIN_LEN + nd._MIN_LEN)
+ data = buf[(icmp._MIN_LEN + nd._MIN_LEN + 8):]
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, nd_csum)
+ eq_(res >> 29, self.res)
+ eq_(dst, addrconv.ipv6.text_to_bin(self.dst))
+ eq_(nd_type, self.nd_type)
+ eq_(nd_length, self.nd_length)
+ eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
+
+ def test_to_string(self):
+ nd_opt = icmpv6.nd_option_tla(self.nd_length, self.nd_hw_src)
+ nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt)
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, nd)
+
+ nd_opt_values = {'length': self.nd_length,
+ 'hw_src': self.nd_hw_src,
+ 'data': None}
+ _nd_opt_str = ','.join(['%s=%s' % (k, repr(nd_opt_values[k]))
+ for k, v in inspect.getmembers(nd_opt)
+ if k in nd_opt_values])
+ nd_opt_str = '%s(%s)' % (icmpv6.nd_option_tla.__name__, _nd_opt_str)
+
+ nd_values = {'res': repr(nd.res),
+ 'dst': repr(self.dst),
+ 'option': nd_opt_str}
+ _nd_str = ','.join(['%s=%s' % (k, nd_values[k])
+ for k, v in inspect.getmembers(nd)
+ if k in nd_values])
+ nd_str = '%s(%s)' % (icmpv6.nd_neighbor.__name__, _nd_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': nd_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+
+ # with nd_option_tla
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_NEIGHBOR_ADVERT,
+ data=icmpv6.nd_neighbor(
+ option=icmpv6.nd_option_tla()))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_neighbor._PACK_STR,
+ six.binary_type(buf[4:24]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+
+ res = struct.unpack(icmpv6.nd_option_tla._PACK_STR,
+ six.binary_type(buf[24:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_TLA)
+ eq_(res[1], len(icmpv6.nd_option_tla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+
+class Test_icmpv6_router_solicit(unittest.TestCase):
+ type_ = 133
+ code = 0
+ csum = 0x97d9
+ res = 0
+ nd_type = 1
+ nd_length = 1
+ nd_hw_src = '12:2d:a5:6d:bc:0f'
+ data = b'\x00\x00\x00\x00\x01\x01\x12\x2d\xa5\x6d\xbc\x0f'
+ buf = b'\x85\x00\x97\xd9'
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ rs = icmpv6.nd_router_solicit(self.res)
+ eq_(rs.res, self.res)
+ eq_(rs.option, None)
+
+ def _test_parser(self, data=None):
+ buf = self.buf + (data or b'')
+ msg, n, _ = icmpv6.icmpv6.parser(buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ if data is not None:
+ eq_(msg.data.res, self.res)
+ eq_(n, None)
+ if data:
+ rs = msg.data.option
+ eq_(rs.length, self.nd_length)
+ eq_(rs.hw_src, self.nd_hw_src)
+ eq_(rs.data, None)
+
+ def test_parser_without_data(self):
+ self._test_parser()
+
+ def test_parser_with_data(self):
+ self._test_parser(self.data)
+
+ def test_serialize_without_data(self):
+ rs = icmpv6.nd_router_solicit(self.res)
+ prev = ipv6(6, 0, 0, 8, 64, 255, self.src_ipv6, self.dst_ipv6)
+ rs_csum = icmpv6_csum(prev, self.buf)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, rs)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ res = struct.unpack_from(rs._PACK_STR, buf, icmp._MIN_LEN)
+ data = buf[(icmp._MIN_LEN + rs._MIN_LEN):]
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, rs_csum)
+ eq_(res[0], self.res)
+ eq_(data, b'')
+
+ def test_serialize_with_data(self):
+ nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src)
+ rs = icmpv6.nd_router_solicit(self.res, nd_opt)
+ prev = ipv6(6, 0, 0, 16, 64, 255, self.src_ipv6, self.dst_ipv6)
+ rs_csum = icmpv6_csum(prev, self.buf + self.data)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, rs)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ res = struct.unpack_from(rs._PACK_STR, buf, icmp._MIN_LEN)
+ (nd_type, nd_length, nd_hw_src) = struct.unpack_from(
+ nd_opt._PACK_STR, buf, icmp._MIN_LEN + rs._MIN_LEN)
+ data = buf[(icmp._MIN_LEN + rs._MIN_LEN + 8):]
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, rs_csum)
+ eq_(res[0], self.res)
+ eq_(nd_type, self.nd_type)
+ eq_(nd_length, self.nd_length)
+ eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
+
+ def test_to_string(self):
+ nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src)
+ rs = icmpv6.nd_router_solicit(self.res, nd_opt)
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, rs)
+
+ nd_opt_values = {'length': self.nd_length,
+ 'hw_src': self.nd_hw_src,
+ 'data': None}
+ _nd_opt_str = ','.join(['%s=%s' % (k, repr(nd_opt_values[k]))
+ for k, v in inspect.getmembers(nd_opt)
+ if k in nd_opt_values])
+ nd_opt_str = '%s(%s)' % (icmpv6.nd_option_sla.__name__, _nd_opt_str)
+
+ rs_values = {'res': repr(rs.res),
+ 'option': nd_opt_str}
+ _rs_str = ','.join(['%s=%s' % (k, rs_values[k])
+ for k, v in inspect.getmembers(rs)
+ if k in rs_values])
+ rs_str = '%s(%s)' % (icmpv6.nd_router_solicit.__name__, _rs_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': rs_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_SOLICIT, data=icmpv6.nd_router_solicit())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_SOLICIT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR,
+ six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+
+ # with nd_option_sla
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_SOLICIT,
+ data=icmpv6.nd_router_solicit(
+ option=icmpv6.nd_option_sla()))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_SOLICIT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR,
+ six.binary_type(buf[4:8]))
+
+ eq_(res[0], 0)
+
+ res = struct.unpack(icmpv6.nd_option_sla._PACK_STR,
+ six.binary_type(buf[8:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_SLA)
+ eq_(res[1], len(icmpv6.nd_option_sla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+ def test_json(self):
+ nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src)
+ rs = icmpv6.nd_router_solicit(self.res, nd_opt)
+ ic1 = icmpv6.icmpv6(self.type_, self.code, self.csum, rs)
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_icmpv6_router_advert(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_advert._PACK_STR,
+ six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+
+ # with nd_option_sla
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_ADVERT,
+ data=icmpv6.nd_router_advert(
+ options=[icmpv6.nd_option_sla()]))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_advert._PACK_STR,
+ six.binary_type(buf[4:16]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+
+ res = struct.unpack(icmpv6.nd_option_sla._PACK_STR,
+ six.binary_type(buf[16:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_SLA)
+ eq_(res[1], len(icmpv6.nd_option_sla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+ # with nd_option_pi
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_ADVERT,
+ data=icmpv6.nd_router_advert(
+ options=[icmpv6.nd_option_pi()]))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_advert._PACK_STR,
+ six.binary_type(buf[4:16]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+
+ res = struct.unpack(icmpv6.nd_option_pi._PACK_STR,
+ six.binary_type(buf[16:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_PI)
+ eq_(res[1], 4)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[7], addrconv.ipv6.text_to_bin('::'))
+
+ # with nd_option_sla and nd_option_pi
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_ADVERT,
+ data=icmpv6.nd_router_advert(
+ options=[icmpv6.nd_option_sla(), icmpv6.nd_option_pi()]))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_advert._PACK_STR,
+ six.binary_type(buf[4:16]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+
+ res = struct.unpack(icmpv6.nd_option_sla._PACK_STR,
+ six.binary_type(buf[16:24]))
+
+ eq_(res[0], icmpv6.ND_OPTION_SLA)
+ eq_(res[1], len(icmpv6.nd_option_sla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+ res = struct.unpack(icmpv6.nd_option_pi._PACK_STR,
+ six.binary_type(buf[24:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_PI)
+ eq_(res[1], len(icmpv6.nd_option_pi()) // 8)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[7], addrconv.ipv6.text_to_bin('::'))
+
+ def test_json(self):
+ ic1 = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_ADVERT,
+ data=icmpv6.nd_router_advert(
+ options=[icmpv6.nd_option_sla(), icmpv6.nd_option_pi()]))
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_icmpv6_nd_option_la(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_default_args(self):
+ la = icmpv6.nd_option_sla()
+ buf = la.serialize()
+ res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], icmpv6.ND_OPTION_SLA)
+ eq_(res[1], len(icmpv6.nd_option_sla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+ # with nd_neighbor
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_NEIGHBOR_ADVERT,
+ data=icmpv6.nd_neighbor(
+ option=icmpv6.nd_option_tla()))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_neighbor._PACK_STR,
+ six.binary_type(buf[4:24]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+
+ res = struct.unpack(icmpv6.nd_option_tla._PACK_STR,
+ six.binary_type(buf[24:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_TLA)
+ eq_(res[1], len(icmpv6.nd_option_tla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+ # with nd_router_solicit
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_SOLICIT,
+ data=icmpv6.nd_router_solicit(
+ option=icmpv6.nd_option_sla()))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_SOLICIT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR,
+ six.binary_type(buf[4:8]))
+
+ eq_(res[0], 0)
+
+ res = struct.unpack(icmpv6.nd_option_sla._PACK_STR,
+ six.binary_type(buf[8:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_SLA)
+ eq_(res[1], len(icmpv6.nd_option_sla()) // 8)
+ eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
+
+
+class Test_icmpv6_nd_option_pi(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_default_args(self):
+ pi = icmpv6.nd_option_pi()
+ buf = pi.serialize()
+ res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], icmpv6.ND_OPTION_PI)
+ eq_(res[1], len(icmpv6.nd_option_pi()) // 8)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[7], addrconv.ipv6.text_to_bin('::'))
+
+ # with nd_router_advert
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.ND_ROUTER_ADVERT,
+ data=icmpv6.nd_router_advert(
+ options=[icmpv6.nd_option_pi()]))
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.ND_ROUTER_ADVERT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.nd_router_advert._PACK_STR,
+ six.binary_type(buf[4:16]))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+
+ res = struct.unpack(icmpv6.nd_option_pi._PACK_STR,
+ six.binary_type(buf[16:]))
+
+ eq_(res[0], icmpv6.ND_OPTION_PI)
+ eq_(res[1], 4)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[7], addrconv.ipv6.text_to_bin('::'))
+
+
+class Test_icmpv6_membership_query(unittest.TestCase):
+ type_ = 130
+ code = 0
+ csum = 0xb5a4
+ maxresp = 10000
+ address = 'ff08::1'
+ buf = b'\x82\x00\xb5\xa4\x27\x10\x00\x00' \
+ + b'\xff\x08\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01'
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ mld = icmpv6.mld(self.maxresp, self.address)
+ eq_(mld.maxresp, self.maxresp)
+ eq_(mld.address, self.address)
+
+ def test_parser(self):
+ msg, n, _ = icmpv6.icmpv6.parser(self.buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ eq_(msg.data.maxresp, self.maxresp)
+ eq_(msg.data.address, self.address)
+ eq_(n, None)
+
+ def test_serialize(self):
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+ prev = ipv6(6, 0, 0, len(self.buf), 64, 255, src_ipv6, dst_ipv6)
+ mld_csum = icmpv6_csum(prev, self.buf)
+
+ mld = icmpv6.mld(self.maxresp, self.address)
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, mld)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0)
+ (maxresp, address) = struct.unpack_from(
+ mld._PACK_STR, buf, icmp._MIN_LEN)
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, mld_csum)
+ eq_(maxresp, self.maxresp)
+ eq_(address, addrconv.ipv6.text_to_bin(self.address))
+
+ def test_to_string(self):
+ ml = icmpv6.mld(self.maxresp, self.address)
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, ml)
+
+ mld_values = {'maxresp': self.maxresp,
+ 'address': self.address}
+ _mld_str = ','.join(['%s=%s' % (k, repr(mld_values[k]))
+ for k, v in inspect.getmembers(ml)
+ if k in mld_values])
+ mld_str = '%s(%s)' % (icmpv6.mld.__name__, _mld_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': mld_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.MLD_LISTENER_QUERY, data=icmpv6.mld())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.MLD_LISTENER_QUERY)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.mld._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+
+ def test_json(self):
+ ic1 = icmpv6.icmpv6(
+ type_=icmpv6.MLD_LISTENER_QUERY,
+ data=icmpv6.mld())
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_icmpv6_membership_report(Test_icmpv6_membership_query):
+ type_ = 131
+ code = 0
+ csum = 0xb4a4
+ maxresp = 10000
+ address = 'ff08::1'
+ buf = b'\x83\x00\xb4\xa4\x27\x10\x00\x00' \
+ + b'\xff\x08\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01'
+
+ def test_json(self):
+ ic1 = icmpv6.icmpv6(
+ type_=icmpv6.MLD_LISTENER_REPOR,
+ data=icmpv6.mld())
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_icmpv6_membership_done(Test_icmpv6_membership_query):
+ type_ = 132
+ code = 0
+ csum = 0xb3a4
+ maxresp = 10000
+ address = 'ff08::1'
+ buf = b'\x84\x00\xb3\xa4\x27\x10\x00\x00' \
+ + b'\xff\x08\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01'
+
+ def test_json(self):
+ ic1 = icmpv6.icmpv6(
+ type_=icmpv6.MLD_LISTENER_DONE,
+ data=icmpv6.mld())
+ jsondict = ic1.to_jsondict()
+ ic2 = icmpv6.icmpv6.from_jsondict(jsondict['icmpv6'])
+ eq_(str(ic1), str(ic2))
+
+
+class Test_mldv2_query(unittest.TestCase):
+ type_ = 130
+ code = 0
+ csum = 0xb5a4
+ maxresp = 10000
+ address = 'ff08::1'
+ s_flg = 0
+ qrv = 2
+ s_qrv = s_flg << 3 | qrv
+ qqic = 10
+ num = 0
+ srcs = []
+
+ mld = icmpv6.mldv2_query(
+ maxresp, address, s_flg, qrv, qqic, num, srcs)
+
+ buf = b'\x82\x00\xb5\xa4\x27\x10\x00\x00' \
+ + b'\xff\x08\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\x02\x0a\x00\x00'
+
+ def setUp(self):
+ pass
+
+ def setUp_with_srcs(self):
+ self.num = 2
+ self.srcs = ['ff80::1', 'ff80::2']
+ self.mld = icmpv6.mldv2_query(
+ self.maxresp, self.address, self.s_flg, self.qrv, self.qqic,
+ self.num, self.srcs)
+ self.buf = b'\x82\x00\xb5\xa4\x27\x10\x00\x00' \
+ + b'\xff\x08\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\x02\x0a\x00\x02' \
+ + b'\xff\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xff\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x02'
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.mld.maxresp, self.maxresp)
+ eq_(self.mld.address, self.address)
+ eq_(self.mld.s_flg, self.s_flg)
+ eq_(self.mld.qrv, self.qrv)
+ eq_(self.mld.qqic, self.qqic)
+ eq_(self.mld.num, self.num)
+ eq_(self.mld.srcs, self.srcs)
+
+ def test_init_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_init()
+
+ def test_parser(self):
+ msg, n, _ = icmpv6.icmpv6.parser(self.buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ eq_(msg.data.maxresp, self.maxresp)
+ eq_(msg.data.address, self.address)
+ eq_(msg.data.s_flg, self.s_flg)
+ eq_(msg.data.qrv, self.qrv)
+ eq_(msg.data.qqic, self.qqic)
+ eq_(msg.data.num, self.num)
+ eq_(msg.data.srcs, self.srcs)
+ eq_(n, None)
+
+ def test_parser_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_parser()
+
+ def test_serialize(self):
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+ prev = ipv6(6, 0, 0, len(self.buf), 64, 255, src_ipv6, dst_ipv6)
+ mld_csum = icmpv6_csum(prev, self.buf)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, self.mld)
+ buf = icmp.serialize(bytearray(), prev)
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR,
+ six.binary_type(buf))
+ (maxresp, address, s_qrv, qqic, num) = struct.unpack_from(
+ self.mld._PACK_STR, six.binary_type(buf), icmp._MIN_LEN)
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, mld_csum)
+ eq_(maxresp, self.maxresp)
+ eq_(address, addrconv.ipv6.text_to_bin(self.address))
+ s_flg = (s_qrv >> 3) & 0b1
+ qrv = s_qrv & 0b111
+ eq_(s_flg, self.s_flg)
+ eq_(qrv, self.qrv)
+ eq_(qqic, self.qqic)
+ eq_(num, self.num)
+
+ def test_serialize_with_srcs(self):
+ self.setUp_with_srcs()
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+ prev = ipv6(6, 0, 0, len(self.buf), 64, 255, src_ipv6, dst_ipv6)
+ mld_csum = icmpv6_csum(prev, self.buf)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, self.mld)
+ buf = icmp.serialize(bytearray(), prev)
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR,
+ six.binary_type(buf))
+ (maxresp, address, s_qrv, qqic, num) = struct.unpack_from(
+ self.mld._PACK_STR, six.binary_type(buf), icmp._MIN_LEN)
+ (addr1, addr2) = struct.unpack_from(
+ '!16s16s', six.binary_type(buf), icmp._MIN_LEN + self.mld._MIN_LEN)
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, mld_csum)
+ eq_(maxresp, self.maxresp)
+ eq_(address, addrconv.ipv6.text_to_bin(self.address))
+ s_flg = (s_qrv >> 3) & 0b1
+ qrv = s_qrv & 0b111
+ eq_(s_flg, self.s_flg)
+ eq_(qrv, self.qrv)
+ eq_(qqic, self.qqic)
+ eq_(num, self.num)
+ eq_(addr1, addrconv.ipv6.text_to_bin(self.srcs[0]))
+ eq_(addr2, addrconv.ipv6.text_to_bin(self.srcs[1]))
+
+ def _build_mldv2_query(self):
+ e = ethernet(ethertype=ether.ETH_TYPE_IPV6)
+ i = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(type_=icmpv6.MLD_LISTENER_QUERY,
+ data=self.mld)
+ p = e / i / ic
+ return p
+
+ def test_build_mldv2_query(self):
+ p = self._build_mldv2_query()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_IPV6)
+
+ i = self.find_protocol(p, "ipv6")
+ ok_(i)
+ eq_(i.nxt, inet.IPPROTO_ICMPV6)
+
+ ic = self.find_protocol(p, "icmpv6")
+ ok_(ic)
+ eq_(ic.type_, icmpv6.MLD_LISTENER_QUERY)
+
+ eq_(ic.data.maxresp, self.maxresp)
+ eq_(ic.data.address, self.address)
+ eq_(ic.data.s_flg, self.s_flg)
+ eq_(ic.data.qrv, self.qrv)
+ eq_(ic.data.num, self.num)
+ eq_(ic.data.srcs, self.srcs)
+
+ def test_build_mldv2_query_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_build_mldv2_query()
+
+ def test_to_string(self):
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, self.mld)
+
+ mld_values = {'maxresp': self.maxresp,
+ 'address': self.address,
+ 's_flg': self.s_flg,
+ 'qrv': self.qrv,
+ 'qqic': self.qqic,
+ 'num': self.num,
+ 'srcs': self.srcs}
+ _mld_str = ','.join(['%s=%s' % (k, repr(mld_values[k]))
+ for k, v in inspect.getmembers(self.mld)
+ if k in mld_values])
+ mld_str = '%s(%s)' % (icmpv6.mldv2_query.__name__, _mld_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': mld_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_to_string_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_to_string()
+
+ @raises(Exception)
+ def test_num_larger_than_srcs(self):
+ self.srcs = ['ff80::1', 'ff80::2', 'ff80::3']
+ self.num = len(self.srcs) + 1
+ self.buf = pack(icmpv6.mldv2_query._PACK_STR, self.maxresp,
+ addrconv.ipv6.text_to_bin(self.address),
+ self.s_qrv, self.qqic, self.num)
+ for src in self.srcs:
+ self.buf += pack('16s', addrconv.ipv6.text_to_bin(src))
+ self.mld = icmpv6.mldv2_query(
+ self.maxresp, self.address, self.s_flg, self.qrv, self.qqic,
+ self.num, self.srcs)
+ self.test_parser()
+
+ @raises(Exception)
+ def test_num_smaller_than_srcs(self):
+ self.srcs = ['ff80::1', 'ff80::2', 'ff80::3']
+ self.num = len(self.srcs) - 1
+ self.buf = pack(icmpv6.mldv2_query._PACK_STR, self.maxresp,
+ addrconv.ipv6.text_to_bin(self.address),
+ self.s_qrv, self.qqic, self.num)
+ for src in self.srcs:
+ self.buf += pack('16s', addrconv.ipv6.text_to_bin(src))
+ self.mld = icmpv6.mldv2_query(
+ self.maxresp, self.address, self.s_flg, self.qrv, self.qqic,
+ self.num, self.srcs)
+ self.test_parser()
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.MLD_LISTENER_QUERY, data=icmpv6.mldv2_query())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.MLD_LISTENER_QUERY)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.mldv2_query._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+ eq_(res[2], 2)
+ eq_(res[3], 0)
+ eq_(res[4], 0)
+
+ # srcs without num
+ srcs = ['ff80::1', 'ff80::2', 'ff80::3']
+ que = icmpv6.mldv2_query(srcs=srcs)
+ buf = que.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_query._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], addrconv.ipv6.text_to_bin('::'))
+ eq_(res[2], 2)
+ eq_(res[3], 0)
+ eq_(res[4], len(srcs))
+
+ (src1, src2, src3) = struct.unpack_from(
+ '16s16s16s', six.binary_type(buf), icmpv6.mldv2_query._MIN_LEN)
+
+ eq_(src1, addrconv.ipv6.text_to_bin(srcs[0]))
+ eq_(src2, addrconv.ipv6.text_to_bin(srcs[1]))
+ eq_(src3, addrconv.ipv6.text_to_bin(srcs[2]))
+
+ def test_json(self):
+ jsondict = self.mld.to_jsondict()
+ mld = icmpv6.mldv2_query.from_jsondict(jsondict['mldv2_query'])
+ eq_(str(self.mld), str(mld))
+
+ def test_json_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_json()
+
+
+class Test_mldv2_report(unittest.TestCase):
+ type_ = 143
+ code = 0
+ csum = 0xb5a4
+ record_num = 0
+ records = []
+
+ mld = icmpv6.mldv2_report(record_num, records)
+
+ buf = b'\x8f\x00\xb5\xa4\x00\x00\x00\x00'
+
+ def setUp(self):
+ pass
+
+ def setUp_with_records(self):
+ self.record1 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 0, 'ff00::1')
+ self.record2 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 2, 'ff00::2',
+ ['fe80::1', 'fe80::2'])
+ self.record3 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 1, 0, 'ff00::3', [], b'abc\x00')
+ self.record4 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 2, 2, 'ff00::4',
+ ['fe80::1', 'fe80::2'], b'abcde\x00\x00\x00')
+ self.records = [self.record1, self.record2, self.record3,
+ self.record4]
+ self.record_num = len(self.records)
+ self.mld = icmpv6.mldv2_report(self.record_num, self.records)
+ self.buf = b'\x8f\x00\xb5\xa4\x00\x00\x00\x04' \
+ + b'\x01\x00\x00\x00' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\x01\x00\x00\x02' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x02' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x02' \
+ + b'\x01\x01\x00\x00' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x03' \
+ + b'\x61\x62\x63\x00' \
+ + b'\x01\x02\x00\x02' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x04' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x02' \
+ + b'\x61\x62\x63\x64\x65\x00\x00\x00'
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.mld.record_num, self.record_num)
+ eq_(self.mld.records, self.records)
+
+ def test_init_with_records(self):
+ self.setUp_with_records()
+ self.test_init()
+
+ def test_parser(self):
+ msg, n, _ = icmpv6.icmpv6.parser(self.buf)
+
+ eq_(msg.type_, self.type_)
+ eq_(msg.code, self.code)
+ eq_(msg.csum, self.csum)
+ eq_(msg.data.record_num, self.record_num)
+ eq_(repr(msg.data.records), repr(self.records))
+
+ def test_parser_with_records(self):
+ self.setUp_with_records()
+ self.test_parser()
+
+ def test_serialize(self):
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+ prev = ipv6(6, 0, 0, len(self.buf), 64, 255, src_ipv6, dst_ipv6)
+ mld_csum = icmpv6_csum(prev, self.buf)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, self.mld)
+ buf = icmp.serialize(bytearray(), prev)
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR,
+ six.binary_type(buf))
+ (record_num, ) = struct.unpack_from(
+ self.mld._PACK_STR, six.binary_type(buf), icmp._MIN_LEN)
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, mld_csum)
+ eq_(record_num, self.record_num)
+
+ def test_serialize_with_records(self):
+ self.setUp_with_records()
+ src_ipv6 = '3ffe:507:0:1:200:86ff:fe05:80da'
+ dst_ipv6 = '3ffe:501:0:1001::2'
+ prev = ipv6(6, 0, 0, len(self.buf), 64, 255, src_ipv6, dst_ipv6)
+ mld_csum = icmpv6_csum(prev, self.buf)
+
+ icmp = icmpv6.icmpv6(self.type_, self.code, 0, self.mld)
+ buf = six.binary_type(icmp.serialize(bytearray(), prev))
+
+ (type_, code, csum) = struct.unpack_from(icmp._PACK_STR,
+ six.binary_type(buf))
+ (record_num, ) = struct.unpack_from(
+ self.mld._PACK_STR, six.binary_type(buf), icmp._MIN_LEN)
+ offset = icmp._MIN_LEN + self.mld._MIN_LEN
+ rec1 = icmpv6.mldv2_report_group.parser(buf[offset:])
+ offset += len(rec1)
+ rec2 = icmpv6.mldv2_report_group.parser(buf[offset:])
+ offset += len(rec2)
+ rec3 = icmpv6.mldv2_report_group.parser(buf[offset:])
+ offset += len(rec3)
+ rec4 = icmpv6.mldv2_report_group.parser(buf[offset:])
+
+ eq_(type_, self.type_)
+ eq_(code, self.code)
+ eq_(csum, mld_csum)
+ eq_(record_num, self.record_num)
+ eq_(repr(rec1), repr(self.record1))
+ eq_(repr(rec2), repr(self.record2))
+ eq_(repr(rec3), repr(self.record3))
+ eq_(repr(rec4), repr(self.record4))
+
+ def _build_mldv2_report(self):
+ e = ethernet(ethertype=ether.ETH_TYPE_IPV6)
+ i = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(type_=icmpv6.MLDV2_LISTENER_REPORT,
+ data=self.mld)
+ p = e / i / ic
+ return p
+
+ def test_build_mldv2_report(self):
+ p = self._build_mldv2_report()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_IPV6)
+
+ i = self.find_protocol(p, "ipv6")
+ ok_(i)
+ eq_(i.nxt, inet.IPPROTO_ICMPV6)
+
+ ic = self.find_protocol(p, "icmpv6")
+ ok_(ic)
+ eq_(ic.type_, icmpv6.MLDV2_LISTENER_REPORT)
+
+ eq_(ic.data.record_num, self.record_num)
+ eq_(ic.data.records, self.records)
+
+ def test_build_mldv2_report_with_records(self):
+ self.setUp_with_records()
+ self.test_build_mldv2_report()
+
+ def test_to_string(self):
+ ic = icmpv6.icmpv6(self.type_, self.code, self.csum, self.mld)
+
+ mld_values = {'record_num': self.record_num,
+ 'records': self.records}
+ _mld_str = ','.join(['%s=%s' % (k, repr(mld_values[k]))
+ for k, v in inspect.getmembers(self.mld)
+ if k in mld_values])
+ mld_str = '%s(%s)' % (icmpv6.mldv2_report.__name__, _mld_str)
+
+ icmp_values = {'type_': repr(self.type_),
+ 'code': repr(self.code),
+ 'csum': repr(self.csum),
+ 'data': mld_str}
+ _ic_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, v in inspect.getmembers(ic)
+ if k in icmp_values])
+ ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str)
+
+ eq_(str(ic), ic_str)
+ eq_(repr(ic), ic_str)
+
+ def test_to_string_with_records(self):
+ self.setUp_with_records()
+ self.test_to_string()
+
+ @raises(Exception)
+ def test_record_num_larger_than_records(self):
+ self.record1 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 0, 'ff00::1')
+ self.record2 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 2, 'ff00::2',
+ ['fe80::1', 'fe80::2'])
+ self.record3 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 1, 0, 'ff00::3', [], b'abc\x00')
+ self.record4 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 2, 2, 'ff00::4',
+ ['fe80::1', 'fe80::2'], b'abcde\x00\x00\x00')
+ self.records = [self.record1, self.record2, self.record3,
+ self.record4]
+ self.record_num = len(self.records) + 1
+ self.buf = struct.pack(
+ icmpv6.mldv2_report._PACK_STR, self.record_num)
+ self.buf += self.record1.serialize()
+ self.buf += self.record2.serialize()
+ self.buf += self.record3.serialize()
+ self.buf += self.record4.serialize()
+ self.mld = icmpv6.mldv2_report(self.record_num, self.records)
+ self.test_parser()
+
+ @raises(Exception)
+ def test_record_num_smaller_than_records(self):
+ self.record1 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 0, 'ff00::1')
+ self.record2 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 2, 'ff00::2',
+ ['fe80::1', 'fe80::2'])
+ self.record3 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 1, 0, 'ff00::3', [], b'abc\x00')
+ self.record4 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 2, 2, 'ff00::4',
+ ['fe80::1', 'fe80::2'], b'abcde\x00\x00\x00')
+ self.records = [self.record1, self.record2, self.record3,
+ self.record4]
+ self.record_num = len(self.records) - 1
+ self.buf = struct.pack(
+ icmpv6.mldv2_report._PACK_STR, self.record_num)
+ self.buf += self.record1.serialize()
+ self.buf += self.record2.serialize()
+ self.buf += self.record3.serialize()
+ self.buf += self.record4.serialize()
+ self.mld = icmpv6.mldv2_report(self.record_num, self.records)
+ self.test_parser()
+
+ def test_default_args(self):
+ prev = ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6(
+ type_=icmpv6.MLDV2_LISTENER_REPORT, data=icmpv6.mldv2_report())
+ prev.serialize(ic, None)
+ buf = ic.serialize(bytearray(), prev)
+ res = struct.unpack(icmpv6.icmpv6._PACK_STR, six.binary_type(buf[:4]))
+
+ eq_(res[0], icmpv6.MLDV2_LISTENER_REPORT)
+ eq_(res[1], 0)
+ eq_(res[2], icmpv6_csum(prev, buf))
+
+ res = struct.unpack(icmpv6.mldv2_report._PACK_STR, six.binary_type(buf[4:]))
+
+ eq_(res[0], 0)
+
+ # records without record_num
+ record1 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 0, 'ff00::1')
+ record2 = icmpv6.mldv2_report_group(
+ icmpv6.MODE_IS_INCLUDE, 0, 2, 'ff00::2',
+ ['fe80::1', 'fe80::2'])
+ records = [record1, record2]
+ rep = icmpv6.mldv2_report(records=records)
+ buf = rep.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], len(records))
+
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf),
+ icmpv6.mldv2_report._MIN_LEN)
+
+ eq_(res[0], icmpv6.MODE_IS_INCLUDE)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.ipv6.text_to_bin('ff00::1'))
+
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf),
+ icmpv6.mldv2_report._MIN_LEN +
+ icmpv6.mldv2_report_group._MIN_LEN)
+
+ eq_(res[0], icmpv6.MODE_IS_INCLUDE)
+ eq_(res[1], 0)
+ eq_(res[2], 2)
+ eq_(res[3], addrconv.ipv6.text_to_bin('ff00::2'))
+
+ res = struct.unpack_from(
+ '16s16s', six.binary_type(buf),
+ icmpv6.mldv2_report._MIN_LEN +
+ icmpv6.mldv2_report_group._MIN_LEN +
+ icmpv6.mldv2_report_group._MIN_LEN)
+
+ eq_(res[0], addrconv.ipv6.text_to_bin('fe80::1'))
+ eq_(res[1], addrconv.ipv6.text_to_bin('fe80::2'))
+
+ def test_json(self):
+ jsondict = self.mld.to_jsondict()
+ mld = icmpv6.mldv2_report.from_jsondict(jsondict['mldv2_report'])
+ eq_(str(self.mld), str(mld))
+
+ def test_json_with_records(self):
+ self.setUp_with_records()
+ self.test_json()
+
+
+class Test_mldv2_report_group(unittest.TestCase):
+ type_ = icmpv6.MODE_IS_INCLUDE
+ aux_len = 0
+ num = 0
+ address = 'ff00::1'
+ srcs = []
+ aux = None
+ mld = icmpv6.mldv2_report_group(
+ type_, aux_len, num, address, srcs, aux)
+ buf = b'\x01\x00\x00\x00' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01'
+
+ def setUp(self):
+ pass
+
+ def setUp_with_srcs(self):
+ self.srcs = ['fe80::1', 'fe80::2', 'fe80::3']
+ self.num = len(self.srcs)
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address, self.srcs,
+ self.aux)
+ self.buf = b'\x01\x00\x00\x03' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x02' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x03'
+
+ def setUp_with_aux(self):
+ self.aux = b'\x01\x02\x03\x04\x05\x06\x07\x08'
+ self.aux_len = len(self.aux) // 4
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address, self.srcs,
+ self.aux)
+ self.buf = b'\x01\x02\x00\x00' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\x01\x02\x03\x04\x05\x06\x07\x08'
+
+ def setUp_with_srcs_and_aux(self):
+ self.srcs = ['fe80::1', 'fe80::2', 'fe80::3']
+ self.num = len(self.srcs)
+ self.aux = b'\x01\x02\x03\x04\x05\x06\x07\x08'
+ self.aux_len = len(self.aux) // 4
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address, self.srcs,
+ self.aux)
+ self.buf = b'\x01\x02\x00\x03' \
+ + b'\xff\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x02' \
+ + b'\xfe\x80\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x03' \
+ + b'\x01\x02\x03\x04\x05\x06\x07\x08'
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.mld.type_, self.type_)
+ eq_(self.mld.aux_len, self.aux_len)
+ eq_(self.mld.num, self.num)
+ eq_(self.mld.address, self.address)
+ eq_(self.mld.srcs, self.srcs)
+ eq_(self.mld.aux, self.aux)
+
+ def test_init_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_init()
+
+ def test_init_with_aux(self):
+ self.setUp_with_aux()
+ self.test_init()
+
+ def test_init_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_init()
+
+ def test_parser(self):
+ _res = icmpv6.mldv2_report_group.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res.type_, self.type_)
+ eq_(res.aux_len, self.aux_len)
+ eq_(res.num, self.num)
+ eq_(res.address, self.address)
+ eq_(res.srcs, self.srcs)
+ eq_(res.aux, self.aux)
+
+ def test_parser_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_parser()
+
+ def test_parser_with_aux(self):
+ self.setUp_with_aux()
+ self.test_parser()
+
+ def test_parser_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_parser()
+
+ def test_serialize(self):
+ buf = self.mld.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv6.text_to_bin(self.address))
+
+ def test_serialize_with_srcs(self):
+ self.setUp_with_srcs()
+ buf = self.mld.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+ (src1, src2, src3) = struct.unpack_from(
+ '16s16s16s', six.binary_type(buf), icmpv6.mldv2_report_group._MIN_LEN)
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv6.text_to_bin(self.address))
+ eq_(src1, addrconv.ipv6.text_to_bin(self.srcs[0]))
+ eq_(src2, addrconv.ipv6.text_to_bin(self.srcs[1]))
+ eq_(src3, addrconv.ipv6.text_to_bin(self.srcs[2]))
+
+ def test_serialize_with_aux(self):
+ self.setUp_with_aux()
+ buf = self.mld.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+ (aux, ) = struct.unpack_from(
+ '%ds' % (self.aux_len * 4), six.binary_type(buf),
+ icmpv6.mldv2_report_group._MIN_LEN)
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv6.text_to_bin(self.address))
+ eq_(aux, self.aux)
+
+ def test_serialize_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ buf = self.mld.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+ (src1, src2, src3) = struct.unpack_from(
+ '16s16s16s', six.binary_type(buf), icmpv6.mldv2_report_group._MIN_LEN)
+ (aux, ) = struct.unpack_from(
+ '%ds' % (self.aux_len * 4), six.binary_type(buf),
+ icmpv6.mldv2_report_group._MIN_LEN + 16 * 3)
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv6.text_to_bin(self.address))
+ eq_(src1, addrconv.ipv6.text_to_bin(self.srcs[0]))
+ eq_(src2, addrconv.ipv6.text_to_bin(self.srcs[1]))
+ eq_(src3, addrconv.ipv6.text_to_bin(self.srcs[2]))
+ eq_(aux, self.aux)
+
+ def test_to_string(self):
+ igmp_values = {'type_': repr(self.type_),
+ 'aux_len': repr(self.aux_len),
+ 'num': repr(self.num),
+ 'address': repr(self.address),
+ 'srcs': repr(self.srcs),
+ 'aux': repr(self.aux)}
+ _g_str = ','.join(['%s=%s' % (k, igmp_values[k])
+ for k, v in inspect.getmembers(self.mld)
+ if k in igmp_values])
+ g_str = '%s(%s)' % (icmpv6.mldv2_report_group.__name__, _g_str)
+
+ eq_(str(self.mld), g_str)
+ eq_(repr(self.mld), g_str)
+
+ def test_to_string_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_to_string()
+
+ def test_to_string_with_aux(self):
+ self.setUp_with_aux()
+ self.test_to_string()
+
+ def test_to_string_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_to_string()
+
+ def test_len(self):
+ eq_(len(self.mld), 20)
+
+ def test_len_with_srcs(self):
+ self.setUp_with_srcs()
+ eq_(len(self.mld), 68)
+
+ def test_len_with_aux(self):
+ self.setUp_with_aux()
+ eq_(len(self.mld), 28)
+
+ def test_len_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ eq_(len(self.mld), 76)
+
+ @raises
+ def test_num_larger_than_srcs(self):
+ self.srcs = ['fe80::1', 'fe80::2', 'fe80::3']
+ self.num = len(self.srcs) + 1
+ self.buf = struct.pack(
+ icmpv6.mldv2_report_group._PACK_STR, self.type_, self.aux_len,
+ self.num, addrconv.ipv6.text_to_bin(self.address))
+ for src in self.srcs:
+ self.buf += pack('16s', addrconv.ipv6.text_to_bin(src))
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ @raises
+ def test_num_smaller_than_srcs(self):
+ self.srcs = ['fe80::1', 'fe80::2', 'fe80::3']
+ self.num = len(self.srcs) - 1
+ self.buf = struct.pack(
+ icmpv6.mldv2_report_group._PACK_STR, self.type_, self.aux_len,
+ self.num, addrconv.ipv6.text_to_bin(self.address))
+ for src in self.srcs:
+ self.buf += pack('16s', addrconv.ipv6.text_to_bin(src))
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ @raises
+ def test_aux_len_larger_than_aux(self):
+ self.aux = b'\x01\x02\x03\x04\x05\x06\x07\x08'
+ self.aux_len = len(self.aux) // 4 + 1
+ self.buf = struct.pack(
+ icmpv6.mldv2_report_group._PACK_STR, self.type_, self.aux_len,
+ self.num, addrconv.ipv6.text_to_bin(self.address))
+ self.buf += self.aux
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ @raises
+ def test_aux_len_smaller_than_aux(self):
+ self.aux = b'\x01\x02\x03\x04\x05\x06\x07\x08'
+ self.aux_len = len(self.aux) // 4 - 1
+ self.buf = struct.pack(
+ icmpv6.mldv2_report_group._PACK_STR, self.type_, self.aux_len,
+ self.num, addrconv.ipv6.text_to_bin(self.address))
+ self.buf += self.aux
+ self.mld = icmpv6.mldv2_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ def test_default_args(self):
+ rep = icmpv6.mldv2_report_group()
+ buf = rep.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.ipv6.text_to_bin('::'))
+
+ # srcs without num
+ srcs = ['fe80::1', 'fe80::2', 'fe80::3']
+ rep = icmpv6.mldv2_report_group(srcs=srcs)
+ buf = rep.serialize()
+ LOG.info(repr(buf))
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], len(srcs))
+ eq_(res[3], addrconv.ipv6.text_to_bin('::'))
+
+ (src1, src2, src3) = struct.unpack_from(
+ '16s16s16s', six.binary_type(buf), icmpv6.mldv2_report_group._MIN_LEN)
+
+ eq_(src1, addrconv.ipv6.text_to_bin(srcs[0]))
+ eq_(src2, addrconv.ipv6.text_to_bin(srcs[1]))
+ eq_(src3, addrconv.ipv6.text_to_bin(srcs[2]))
+
+ # aux without aux_len
+ rep = icmpv6.mldv2_report_group(aux=b'\x01\x02\x03')
+ buf = rep.serialize()
+ res = struct.unpack_from(
+ icmpv6.mldv2_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 1)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.ipv6.text_to_bin('::'))
+ eq_(buf[icmpv6.mldv2_report_group._MIN_LEN:], b'\x01\x02\x03\x00')
+
+ def test_json(self):
+ jsondict = self.mld.to_jsondict()
+ mld = icmpv6.mldv2_report_group.from_jsondict(
+ jsondict['mldv2_report_group'])
+ eq_(str(self.mld), str(mld))
+
+ def test_json_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_json()
+
+ def test_json_with_aux(self):
+ self.setUp_with_aux()
+ self.test_json()
+
+ def test_json_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_json()
diff --git a/tests/unit/packet/test_igmp.py b/tests/unit/packet/test_igmp.py
new file mode 100644
index 00000000..9813450d
--- /dev/null
+++ b/tests/unit/packet/test_igmp.py
@@ -0,0 +1,997 @@
+# Copyright (C) 2013 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 unittest
+import inspect
+import logging
+import six
+
+from struct import pack, unpack_from, pack_into
+from nose.tools import ok_, eq_, raises
+from ryu.ofproto import ether
+from ryu.ofproto import inet
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.ipv4 import ipv4
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet.packet_utils import checksum
+from ryu.lib import addrconv
+from ryu.lib.packet.igmp import igmp
+from ryu.lib.packet.igmp import igmpv3_query
+from ryu.lib.packet.igmp import igmpv3_report
+from ryu.lib.packet.igmp import igmpv3_report_group
+from ryu.lib.packet.igmp import IGMP_TYPE_QUERY
+from ryu.lib.packet.igmp import IGMP_TYPE_REPORT_V3
+from ryu.lib.packet.igmp import MODE_IS_INCLUDE
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_igmp(unittest.TestCase):
+ """ Test case for Internet Group Management Protocol
+ """
+ def setUp(self):
+ self.msgtype = IGMP_TYPE_QUERY
+ self.maxresp = 100
+ self.csum = 0
+ self.address = '225.0.0.1'
+
+ self.buf = pack(igmp._PACK_STR, self.msgtype, self.maxresp,
+ self.csum,
+ addrconv.ipv4.text_to_bin(self.address))
+
+ self.g = igmp(self.msgtype, self.maxresp, self.csum,
+ self.address)
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.msgtype, self.g.msgtype)
+ eq_(self.maxresp, self.g.maxresp)
+ eq_(self.csum, self.g.csum)
+ eq_(self.address, self.g.address)
+
+ def test_parser(self):
+ _res = self.g.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res.msgtype, self.msgtype)
+ eq_(res.maxresp, self.maxresp)
+ eq_(res.csum, self.csum)
+ eq_(res.address, self.address)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.g.serialize(data, prev)
+
+ res = unpack_from(igmp._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], self.msgtype)
+ eq_(res[1], self.maxresp)
+ eq_(res[2], checksum(self.buf))
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+
+ def _build_igmp(self):
+ dl_dst = '11:22:33:44:55:66'
+ dl_src = 'aa:bb:cc:dd:ee:ff'
+ dl_type = ether.ETH_TYPE_IP
+ e = ethernet(dl_dst, dl_src, dl_type)
+
+ total_length = 20 + igmp._MIN_LEN
+ nw_proto = inet.IPPROTO_IGMP
+ nw_dst = '11.22.33.44'
+ nw_src = '55.66.77.88'
+ i = ipv4(total_length=total_length, src=nw_src, dst=nw_dst,
+ proto=nw_proto)
+
+ p = Packet()
+
+ p.add_protocol(e)
+ p.add_protocol(i)
+ p.add_protocol(self.g)
+ p.serialize()
+ return p
+
+ def test_build_igmp(self):
+ p = self._build_igmp()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_IP)
+
+ i = self.find_protocol(p, "ipv4")
+ ok_(i)
+ eq_(i.proto, inet.IPPROTO_IGMP)
+
+ g = self.find_protocol(p, "igmp")
+ ok_(g)
+
+ eq_(g.msgtype, self.msgtype)
+ eq_(g.maxresp, self.maxresp)
+ eq_(g.csum, checksum(self.buf))
+ eq_(g.address, self.address)
+
+ def test_to_string(self):
+ igmp_values = {'msgtype': repr(self.msgtype),
+ 'maxresp': repr(self.maxresp),
+ 'csum': repr(self.csum),
+ 'address': repr(self.address)}
+ _g_str = ','.join(['%s=%s' % (k, igmp_values[k])
+ for k, v in inspect.getmembers(self.g)
+ if k in igmp_values])
+ g_str = '%s(%s)' % (igmp.__name__, _g_str)
+
+ eq_(str(self.g), g_str)
+ eq_(repr(self.g), g_str)
+
+ @raises(Exception)
+ def test_malformed_igmp(self):
+ m_short_buf = self.buf[1:igmp._MIN_LEN]
+ igmp.parser(m_short_buf)
+
+ def test_default_args(self):
+ ig = igmp()
+ buf = ig.serialize(bytearray(), None)
+ res = unpack_from(igmp._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0x11)
+ eq_(res[1], 0)
+ eq_(res[3], addrconv.ipv4.text_to_bin('0.0.0.0'))
+
+ def test_json(self):
+ jsondict = self.g.to_jsondict()
+ g = igmp.from_jsondict(jsondict['igmp'])
+ eq_(str(self.g), str(g))
+
+
+class Test_igmpv3_query(unittest.TestCase):
+ """ Test case for Internet Group Management Protocol v3
+ Membership Query Message"""
+ def setUp(self):
+ self.msgtype = IGMP_TYPE_QUERY
+ self.maxresp = 100
+ self.csum = 0
+ self.address = '225.0.0.1'
+ self.s_flg = 0
+ self.qrv = 2
+ self.qqic = 10
+ self.num = 0
+ self.srcs = []
+
+ self.s_qrv = self.s_flg << 3 | self.qrv
+
+ self.buf = pack(igmpv3_query._PACK_STR, self.msgtype,
+ self.maxresp, self.csum,
+ addrconv.ipv4.text_to_bin(self.address),
+ self.s_qrv, self.qqic, self.num)
+
+ self.g = igmpv3_query(
+ self.msgtype, self.maxresp, self.csum, self.address,
+ self.s_flg, self.qrv, self.qqic, self.num, self.srcs)
+
+ def setUp_with_srcs(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs)
+ self.buf = pack(igmpv3_query._PACK_STR, self.msgtype,
+ self.maxresp, self.csum,
+ addrconv.ipv4.text_to_bin(self.address),
+ self.s_qrv, self.qqic, self.num)
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.g = igmpv3_query(
+ self.msgtype, self.maxresp, self.csum, self.address,
+ self.s_flg, self.qrv, self.qqic, self.num, self.srcs)
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.msgtype, self.g.msgtype)
+ eq_(self.maxresp, self.g.maxresp)
+ eq_(self.csum, self.g.csum)
+ eq_(self.address, self.g.address)
+ eq_(self.s_flg, self.g.s_flg)
+ eq_(self.qrv, self.g.qrv)
+ eq_(self.qqic, self.g.qqic)
+ eq_(self.num, self.g.num)
+ eq_(self.srcs, self.g.srcs)
+
+ def test_init_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_init()
+
+ def test_parser(self):
+ _res = self.g.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res.msgtype, self.msgtype)
+ eq_(res.maxresp, self.maxresp)
+ eq_(res.csum, self.csum)
+ eq_(res.address, self.address)
+ eq_(res.s_flg, self.s_flg)
+ eq_(res.qrv, self.qrv)
+ eq_(res.qqic, self.qqic)
+ eq_(res.num, self.num)
+ eq_(res.srcs, self.srcs)
+
+ def test_parser_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_parser()
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.g.serialize(data, prev)
+
+ res = unpack_from(igmpv3_query._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], self.msgtype)
+ eq_(res[1], self.maxresp)
+ eq_(res[2], checksum(self.buf))
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+ eq_(res[4], self.s_qrv)
+ eq_(res[5], self.qqic)
+ eq_(res[6], self.num)
+
+ def test_serialize_with_srcs(self):
+ self.setUp_with_srcs()
+ data = bytearray()
+ prev = None
+ buf = self.g.serialize(data, prev)
+
+ res = unpack_from(igmpv3_query._PACK_STR, six.binary_type(buf))
+ (src1, src2, src3) = unpack_from('4s4s4s', six.binary_type(buf),
+ igmpv3_query._MIN_LEN)
+
+ eq_(res[0], self.msgtype)
+ eq_(res[1], self.maxresp)
+ eq_(res[2], checksum(self.buf))
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+ eq_(res[4], self.s_qrv)
+ eq_(res[5], self.qqic)
+ eq_(res[6], self.num)
+ eq_(src1, addrconv.ipv4.text_to_bin(self.srcs[0]))
+ eq_(src2, addrconv.ipv4.text_to_bin(self.srcs[1]))
+ eq_(src3, addrconv.ipv4.text_to_bin(self.srcs[2]))
+
+ def _build_igmp(self):
+ dl_dst = '11:22:33:44:55:66'
+ dl_src = 'aa:bb:cc:dd:ee:ff'
+ dl_type = ether.ETH_TYPE_IP
+ e = ethernet(dl_dst, dl_src, dl_type)
+
+ total_length = len(ipv4()) + len(self.g)
+ nw_proto = inet.IPPROTO_IGMP
+ nw_dst = '11.22.33.44'
+ nw_src = '55.66.77.88'
+ i = ipv4(total_length=total_length, src=nw_src, dst=nw_dst,
+ proto=nw_proto, ttl=1)
+
+ p = Packet()
+
+ p.add_protocol(e)
+ p.add_protocol(i)
+ p.add_protocol(self.g)
+ p.serialize()
+ return p
+
+ def test_build_igmp(self):
+ p = self._build_igmp()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_IP)
+
+ i = self.find_protocol(p, "ipv4")
+ ok_(i)
+ eq_(i.proto, inet.IPPROTO_IGMP)
+
+ g = self.find_protocol(p, "igmpv3_query")
+ ok_(g)
+
+ eq_(g.msgtype, self.msgtype)
+ eq_(g.maxresp, self.maxresp)
+ eq_(g.csum, checksum(self.buf))
+ eq_(g.address, self.address)
+ eq_(g.s_flg, self.s_flg)
+ eq_(g.qrv, self.qrv)
+ eq_(g.qqic, self.qqic)
+ eq_(g.num, self.num)
+ eq_(g.srcs, self.srcs)
+
+ def test_build_igmp_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_build_igmp()
+
+ def test_to_string(self):
+ igmp_values = {'msgtype': repr(self.msgtype),
+ 'maxresp': repr(self.maxresp),
+ 'csum': repr(self.csum),
+ 'address': repr(self.address),
+ 's_flg': repr(self.s_flg),
+ 'qrv': repr(self.qrv),
+ 'qqic': repr(self.qqic),
+ 'num': repr(self.num),
+ 'srcs': repr(self.srcs)}
+ _g_str = ','.join(['%s=%s' % (k, igmp_values[k])
+ for k, v in inspect.getmembers(self.g)
+ if k in igmp_values])
+ g_str = '%s(%s)' % (igmpv3_query.__name__, _g_str)
+
+ eq_(str(self.g), g_str)
+ eq_(repr(self.g), g_str)
+
+ def test_to_string_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_to_string()
+
+ @raises(Exception)
+ def test_num_larger_than_srcs(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs) + 1
+ self.buf = pack(igmpv3_query._PACK_STR, self.msgtype,
+ self.maxresp, self.csum,
+ addrconv.ipv4.text_to_bin(self.address),
+ self.s_qrv, self.qqic, self.num)
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.g = igmpv3_query(
+ self.msgtype, self.maxresp, self.csum, self.address,
+ self.s_flg, self.qrv, self.qqic, self.num, self.srcs)
+ self.test_parser()
+
+ @raises(Exception)
+ def test_num_smaller_than_srcs(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs) - 1
+ self.buf = pack(igmpv3_query._PACK_STR, self.msgtype,
+ self.maxresp, self.csum,
+ addrconv.ipv4.text_to_bin(self.address),
+ self.s_qrv, self.qqic, self.num)
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.g = igmpv3_query(
+ self.msgtype, self.maxresp, self.csum, self.address,
+ self.s_flg, self.qrv, self.qqic, self.num, self.srcs)
+ self.test_parser()
+
+ def test_default_args(self):
+ prev = ipv4(proto=inet.IPPROTO_IGMP)
+ g = igmpv3_query()
+ prev.serialize(g, None)
+ buf = g.serialize(bytearray(), prev)
+ res = unpack_from(igmpv3_query._PACK_STR, six.binary_type(buf))
+ buf = bytearray(buf)
+ pack_into('!H', buf, 2, 0)
+
+ eq_(res[0], IGMP_TYPE_QUERY)
+ eq_(res[1], 100)
+ eq_(res[2], checksum(buf))
+ eq_(res[3], addrconv.ipv4.text_to_bin('0.0.0.0'))
+ eq_(res[4], 2)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+
+ # srcs without num
+ prev = ipv4(proto=inet.IPPROTO_IGMP)
+ srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ g = igmpv3_query(srcs=srcs)
+ prev.serialize(g, None)
+ buf = g.serialize(bytearray(), prev)
+ res = unpack_from(igmpv3_query._PACK_STR, six.binary_type(buf))
+ buf = bytearray(buf)
+ pack_into('!H', buf, 2, 0)
+
+ eq_(res[0], IGMP_TYPE_QUERY)
+ eq_(res[1], 100)
+ eq_(res[2], checksum(buf))
+ eq_(res[3], addrconv.ipv4.text_to_bin('0.0.0.0'))
+ eq_(res[4], 2)
+ eq_(res[5], 0)
+ eq_(res[6], len(srcs))
+
+ res = unpack_from('4s4s4s', six.binary_type(buf), igmpv3_query._MIN_LEN)
+
+ eq_(res[0], addrconv.ipv4.text_to_bin(srcs[0]))
+ eq_(res[1], addrconv.ipv4.text_to_bin(srcs[1]))
+ eq_(res[2], addrconv.ipv4.text_to_bin(srcs[2]))
+
+ def test_json(self):
+ jsondict = self.g.to_jsondict()
+ g = igmpv3_query.from_jsondict(jsondict['igmpv3_query'])
+ eq_(str(self.g), str(g))
+
+ def test_json_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_json()
+
+
+class Test_igmpv3_report(unittest.TestCase):
+ """ Test case for Internet Group Management Protocol v3
+ Membership Report Message"""
+ def setUp(self):
+ self.msgtype = IGMP_TYPE_REPORT_V3
+ self.csum = 0
+ self.record_num = 0
+ self.records = []
+
+ self.buf = pack(igmpv3_report._PACK_STR, self.msgtype,
+ self.csum, self.record_num)
+
+ self.g = igmpv3_report(
+ self.msgtype, self.csum, self.record_num, self.records)
+
+ def setUp_with_records(self):
+ self.record1 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 0, '225.0.0.1')
+ self.record2 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 2, '225.0.0.2',
+ ['172.16.10.10', '172.16.10.27'])
+ self.record3 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 0, '225.0.0.3', [], b'abc\x00')
+ self.record4 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 2, 2, '225.0.0.4',
+ ['172.16.10.10', '172.16.10.27'], b'abcde\x00\x00\x00')
+ self.records = [self.record1, self.record2, self.record3,
+ self.record4]
+ self.record_num = len(self.records)
+ self.buf = pack(igmpv3_report._PACK_STR, self.msgtype,
+ self.csum, self.record_num)
+ self.buf += self.record1.serialize()
+ self.buf += self.record2.serialize()
+ self.buf += self.record3.serialize()
+ self.buf += self.record4.serialize()
+ self.g = igmpv3_report(
+ self.msgtype, self.csum, self.record_num, self.records)
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.msgtype, self.g.msgtype)
+ eq_(self.csum, self.g.csum)
+ eq_(self.record_num, self.g.record_num)
+ eq_(self.records, self.g.records)
+
+ def test_init_with_records(self):
+ self.setUp_with_records()
+ self.test_init()
+
+ def test_parser(self):
+ _res = self.g.parser(six.binary_type(self.buf))
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res.msgtype, self.msgtype)
+ eq_(res.csum, self.csum)
+ eq_(res.record_num, self.record_num)
+ eq_(repr(res.records), repr(self.records))
+
+ def test_parser_with_records(self):
+ self.setUp_with_records()
+ self.test_parser()
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.g.serialize(data, prev)
+
+ res = unpack_from(igmpv3_report._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], self.msgtype)
+ eq_(res[1], checksum(self.buf))
+ eq_(res[2], self.record_num)
+
+ def test_serialize_with_records(self):
+ self.setUp_with_records()
+ data = bytearray()
+ prev = None
+ buf = six.binary_type(self.g.serialize(data, prev))
+
+ res = unpack_from(igmpv3_report._PACK_STR, buf)
+ offset = igmpv3_report._MIN_LEN
+ rec1 = igmpv3_report_group.parser(buf[offset:])
+ offset += len(rec1)
+ rec2 = igmpv3_report_group.parser(buf[offset:])
+ offset += len(rec2)
+ rec3 = igmpv3_report_group.parser(buf[offset:])
+ offset += len(rec3)
+ rec4 = igmpv3_report_group.parser(buf[offset:])
+
+ eq_(res[0], self.msgtype)
+ eq_(res[1], checksum(self.buf))
+ eq_(res[2], self.record_num)
+ eq_(repr(rec1), repr(self.record1))
+ eq_(repr(rec2), repr(self.record2))
+ eq_(repr(rec3), repr(self.record3))
+ eq_(repr(rec4), repr(self.record4))
+
+ def _build_igmp(self):
+ dl_dst = '11:22:33:44:55:66'
+ dl_src = 'aa:bb:cc:dd:ee:ff'
+ dl_type = ether.ETH_TYPE_IP
+ e = ethernet(dl_dst, dl_src, dl_type)
+
+ total_length = len(ipv4()) + len(self.g)
+ nw_proto = inet.IPPROTO_IGMP
+ nw_dst = '11.22.33.44'
+ nw_src = '55.66.77.88'
+ i = ipv4(total_length=total_length, src=nw_src, dst=nw_dst,
+ proto=nw_proto, ttl=1)
+
+ p = Packet()
+
+ p.add_protocol(e)
+ p.add_protocol(i)
+ p.add_protocol(self.g)
+ p.serialize()
+ return p
+
+ def test_build_igmp(self):
+ p = self._build_igmp()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_IP)
+
+ i = self.find_protocol(p, "ipv4")
+ ok_(i)
+ eq_(i.proto, inet.IPPROTO_IGMP)
+
+ g = self.find_protocol(p, "igmpv3_report")
+ ok_(g)
+
+ eq_(g.msgtype, self.msgtype)
+ eq_(g.csum, checksum(self.buf))
+ eq_(g.record_num, self.record_num)
+ eq_(g.records, self.records)
+
+ def test_build_igmp_with_records(self):
+ self.setUp_with_records()
+ self.test_build_igmp()
+
+ def test_to_string(self):
+ igmp_values = {'msgtype': repr(self.msgtype),
+ 'csum': repr(self.csum),
+ 'record_num': repr(self.record_num),
+ 'records': repr(self.records)}
+ _g_str = ','.join(['%s=%s' % (k, igmp_values[k])
+ for k, v in inspect.getmembers(self.g)
+ if k in igmp_values])
+ g_str = '%s(%s)' % (igmpv3_report.__name__, _g_str)
+
+ eq_(str(self.g), g_str)
+ eq_(repr(self.g), g_str)
+
+ def test_to_string_with_records(self):
+ self.setUp_with_records()
+ self.test_to_string()
+
+ @raises(Exception)
+ def test_record_num_larger_than_records(self):
+ self.record1 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 0, '225.0.0.1')
+ self.record2 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 2, '225.0.0.2',
+ ['172.16.10.10', '172.16.10.27'])
+ self.record3 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 0, '225.0.0.3', [], b'abc\x00')
+ self.record4 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 2, '225.0.0.4',
+ ['172.16.10.10', '172.16.10.27'], b'abc\x00')
+ self.records = [self.record1, self.record2, self.record3,
+ self.record4]
+ self.record_num = len(self.records) + 1
+ self.buf = pack(igmpv3_report._PACK_STR, self.msgtype,
+ self.csum, self.record_num)
+ self.buf += self.record1.serialize()
+ self.buf += self.record2.serialize()
+ self.buf += self.record3.serialize()
+ self.buf += self.record4.serialize()
+ self.g = igmpv3_report(
+ self.msgtype, self.csum, self.record_num, self.records)
+ self.test_parser()
+
+ @raises(Exception)
+ def test_record_num_smaller_than_records(self):
+ self.record1 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 0, '225.0.0.1')
+ self.record2 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 2, '225.0.0.2',
+ ['172.16.10.10', '172.16.10.27'])
+ self.record3 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 0, '225.0.0.3', [], b'abc\x00')
+ self.record4 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 2, '225.0.0.4',
+ ['172.16.10.10', '172.16.10.27'], b'abc\x00')
+ self.records = [self.record1, self.record2, self.record3,
+ self.record4]
+ self.record_num = len(self.records) - 1
+ self.buf = pack(igmpv3_report._PACK_STR, self.msgtype,
+ self.csum, self.record_num)
+ self.buf += self.record1.serialize()
+ self.buf += self.record2.serialize()
+ self.buf += self.record3.serialize()
+ self.buf += self.record4.serialize()
+ self.g = igmpv3_report(
+ self.msgtype, self.csum, self.record_num, self.records)
+ self.test_parser()
+
+ def test_default_args(self):
+ prev = ipv4(proto=inet.IPPROTO_IGMP)
+ g = igmpv3_report()
+ prev.serialize(g, None)
+ buf = g.serialize(bytearray(), prev)
+ res = unpack_from(igmpv3_report._PACK_STR, six.binary_type(buf))
+ buf = bytearray(buf)
+ pack_into('!H', buf, 2, 0)
+
+ eq_(res[0], IGMP_TYPE_REPORT_V3)
+ eq_(res[1], checksum(buf))
+ eq_(res[2], 0)
+
+ # records without record_num
+ prev = ipv4(proto=inet.IPPROTO_IGMP)
+ record1 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 0, '225.0.0.1')
+ record2 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 0, 2, '225.0.0.2',
+ ['172.16.10.10', '172.16.10.27'])
+ record3 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 0, '225.0.0.3', [], b'abc\x00')
+ record4 = igmpv3_report_group(
+ MODE_IS_INCLUDE, 1, 2, '225.0.0.4',
+ ['172.16.10.10', '172.16.10.27'], b'abc\x00')
+ records = [record1, record2, record3, record4]
+ g = igmpv3_report(records=records)
+ prev.serialize(g, None)
+ buf = g.serialize(bytearray(), prev)
+ res = unpack_from(igmpv3_report._PACK_STR, six.binary_type(buf))
+ buf = bytearray(buf)
+ pack_into('!H', buf, 2, 0)
+
+ eq_(res[0], IGMP_TYPE_REPORT_V3)
+ eq_(res[1], checksum(buf))
+ eq_(res[2], len(records))
+
+ def test_json(self):
+ jsondict = self.g.to_jsondict()
+ g = igmpv3_report.from_jsondict(jsondict['igmpv3_report'])
+ eq_(str(self.g), str(g))
+
+ def test_json_with_records(self):
+ self.setUp_with_records()
+ self.test_json()
+
+
+class Test_igmpv3_report_group(unittest.TestCase):
+ """Test case for Group Records of
+ Internet Group Management Protocol v3 Membership Report Message"""
+ def setUp(self):
+ self.type_ = MODE_IS_INCLUDE
+ self.aux_len = 0
+ self.num = 0
+ self.address = '225.0.0.1'
+ self.srcs = []
+ self.aux = None
+
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+
+ def setUp_with_srcs(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs)
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+
+ def setUp_with_aux(self):
+ self.aux = b'\x01\x02\x03\x04\x05\x00\x00\x00'
+ self.aux_len = len(self.aux) // 4
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ self.buf += self.aux
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+
+ def setUp_with_srcs_and_aux(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs)
+ self.aux = b'\x01\x02\x03\x04\x05\x00\x00\x00'
+ self.aux_len = len(self.aux) // 4
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.buf += self.aux
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.type_, self.g.type_)
+ eq_(self.aux_len, self.g.aux_len)
+ eq_(self.num, self.g.num)
+ eq_(self.address, self.g.address)
+ eq_(self.srcs, self.g.srcs)
+ eq_(self.aux, self.g.aux)
+
+ def test_init_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_init()
+
+ def test_init_with_aux(self):
+ self.setUp_with_aux()
+ self.test_init()
+
+ def test_init_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_init()
+
+ def test_parser(self):
+ _res = self.g.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res.type_, self.type_)
+ eq_(res.aux_len, self.aux_len)
+ eq_(res.num, self.num)
+ eq_(res.address, self.address)
+ eq_(res.srcs, self.srcs)
+ eq_(res.aux, self.aux)
+
+ def test_parser_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_parser()
+
+ def test_parser_with_aux(self):
+ self.setUp_with_aux()
+ self.test_parser()
+
+ def test_parser_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_parser()
+
+ def test_serialize(self):
+ buf = self.g.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+
+ def test_serialize_with_srcs(self):
+ self.setUp_with_srcs()
+ buf = self.g.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+ (src1, src2, src3) = unpack_from('4s4s4s', six.binary_type(buf),
+ igmpv3_report_group._MIN_LEN)
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+ eq_(src1, addrconv.ipv4.text_to_bin(self.srcs[0]))
+ eq_(src2, addrconv.ipv4.text_to_bin(self.srcs[1]))
+ eq_(src3, addrconv.ipv4.text_to_bin(self.srcs[2]))
+
+ def test_serialize_with_aux(self):
+ self.setUp_with_aux()
+ buf = self.g.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+ (aux, ) = unpack_from('%ds' % (self.aux_len * 4), six.binary_type(buf),
+ igmpv3_report_group._MIN_LEN)
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+ eq_(aux, self.aux)
+
+ def test_serialize_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ buf = self.g.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+ (src1, src2, src3) = unpack_from('4s4s4s', six.binary_type(buf),
+ igmpv3_report_group._MIN_LEN)
+ (aux, ) = unpack_from('%ds' % (self.aux_len * 4), six.binary_type(buf),
+ igmpv3_report_group._MIN_LEN + 12)
+ eq_(res[0], self.type_)
+ eq_(res[1], self.aux_len)
+ eq_(res[2], self.num)
+ eq_(res[3], addrconv.ipv4.text_to_bin(self.address))
+ eq_(src1, addrconv.ipv4.text_to_bin(self.srcs[0]))
+ eq_(src2, addrconv.ipv4.text_to_bin(self.srcs[1]))
+ eq_(src3, addrconv.ipv4.text_to_bin(self.srcs[2]))
+ eq_(aux, self.aux)
+
+ def test_to_string(self):
+ igmp_values = {'type_': repr(self.type_),
+ 'aux_len': repr(self.aux_len),
+ 'num': repr(self.num),
+ 'address': repr(self.address),
+ 'srcs': repr(self.srcs),
+ 'aux': repr(self.aux)}
+ _g_str = ','.join(['%s=%s' % (k, igmp_values[k])
+ for k, v in inspect.getmembers(self.g)
+ if k in igmp_values])
+ g_str = '%s(%s)' % (igmpv3_report_group.__name__, _g_str)
+
+ eq_(str(self.g), g_str)
+ eq_(repr(self.g), g_str)
+
+ def test_to_string_with_srcs(self):
+ self.setUp_with_srcs()
+ self.test_to_string()
+
+ def test_to_string_with_aux(self):
+ self.setUp_with_aux()
+ self.test_to_string()
+
+ def test_to_string_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ self.test_to_string()
+
+ def test_len(self):
+ eq_(len(self.g), 8)
+
+ def test_len_with_srcs(self):
+ self.setUp_with_srcs()
+ eq_(len(self.g), 20)
+
+ def test_len_with_aux(self):
+ self.setUp_with_aux()
+ eq_(len(self.g), 16)
+
+ def test_len_with_srcs_and_aux(self):
+ self.setUp_with_srcs_and_aux()
+ eq_(len(self.g), 28)
+
+ @raises
+ def test_num_larger_than_srcs(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs) + 1
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ @raises
+ def test_num_smaller_than_srcs(self):
+ self.srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ self.num = len(self.srcs) - 1
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ for src in self.srcs:
+ self.buf += pack('4s', addrconv.ipv4.text_to_bin(src))
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ @raises
+ def test_aux_len_larger_than_aux(self):
+ self.aux = b'\x01\x02\x03\x04\x05\x00\x00\x00'
+ self.aux_len = len(self.aux) // 4 + 1
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ self.buf += self.aux
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ @raises
+ def test_aux_len_smaller_than_aux(self):
+ self.aux = b'\x01\x02\x03\x04\x05\x00\x00\x00'
+ self.aux_len = len(self.aux) // 4 - 1
+ self.buf = pack(igmpv3_report_group._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv4.text_to_bin(self.address))
+ self.buf += self.aux
+ self.g = igmpv3_report_group(
+ self.type_, self.aux_len, self.num, self.address,
+ self.srcs, self.aux)
+ self.test_parser()
+
+ def test_default_args(self):
+ rep = igmpv3_report_group()
+ buf = rep.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.ipv4.text_to_bin('0.0.0.0'))
+
+ # srcs without num
+ srcs = ['192.168.1.1', '192.168.1.2', '192.168.1.3']
+ rep = igmpv3_report_group(srcs=srcs)
+ buf = rep.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 0)
+ eq_(res[2], len(srcs))
+ eq_(res[3], addrconv.ipv4.text_to_bin('0.0.0.0'))
+
+ res = unpack_from('4s4s4s', six.binary_type(buf),
+ igmpv3_report_group._MIN_LEN)
+
+ eq_(res[0], addrconv.ipv4.text_to_bin(srcs[0]))
+ eq_(res[1], addrconv.ipv4.text_to_bin(srcs[1]))
+ eq_(res[2], addrconv.ipv4.text_to_bin(srcs[2]))
+
+ # aux without aux_len
+ aux = b'abcde'
+ rep = igmpv3_report_group(aux=aux)
+ buf = rep.serialize()
+ res = unpack_from(igmpv3_report_group._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 0)
+ eq_(res[1], 2)
+ eq_(res[2], 0)
+ eq_(res[3], addrconv.ipv4.text_to_bin('0.0.0.0'))
+ eq_(buf[igmpv3_report_group._MIN_LEN:], b'abcde\x00\x00\x00')
diff --git a/tests/unit/packet/test_ipv4.py b/tests/unit/packet/test_ipv4.py
new file mode 100644
index 00000000..69186f3f
--- /dev/null
+++ b/tests/unit/packet/test_ipv4.py
@@ -0,0 +1,137 @@
+# 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 unittest
+import logging
+import six
+import struct
+from struct import *
+from nose.tools import *
+from ryu.ofproto import ether, inet
+from ryu.lib.packet import packet_utils
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet.ipv4 import ipv4
+from ryu.lib.packet.tcp import tcp
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger('test_ipv4')
+
+
+class Test_ipv4(unittest.TestCase):
+ """ Test case for ipv4
+ """
+
+ version = 4
+ header_length = 5 + 10
+ ver_hlen = version << 4 | header_length
+ tos = 0
+ total_length = header_length + 64
+ identification = 30774
+ flags = 4
+ offset = 1480
+ flg_off = flags << 13 | offset
+ ttl = 64
+ proto = inet.IPPROTO_TCP
+ csum = 0xadc6
+ src = '131.151.32.21'
+ dst = '131.151.32.129'
+ length = header_length * 4
+ option = b'\x86\x28\x00\x00\x00\x01\x01\x22' \
+ + b'\x00\x01\xae\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00\x00\x00\x00\x01'
+
+ buf = pack(ipv4._PACK_STR, ver_hlen, tos, total_length, identification,
+ flg_off, ttl, proto, csum,
+ addrconv.ipv4.text_to_bin(src),
+ addrconv.ipv4.text_to_bin(dst)) \
+ + option
+
+ ip = ipv4(version, header_length, tos, total_length, identification,
+ flags, offset, ttl, proto, csum, src, dst, option)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.version, self.ip.version)
+ eq_(self.header_length, self.ip.header_length)
+ eq_(self.tos, self.ip.tos)
+ eq_(self.total_length, self.ip.total_length)
+ eq_(self.identification, self.ip.identification)
+ eq_(self.flags, self.ip.flags)
+ eq_(self.offset, self.ip.offset)
+ eq_(self.ttl, self.ip.ttl)
+ eq_(self.proto, self.ip.proto)
+ eq_(self.csum, self.ip.csum)
+ eq_(self.src, self.ip.src)
+ eq_(self.dst, self.ip.dst)
+ eq_(self.length, len(self.ip))
+ eq_(self.option, self.ip.option)
+
+ def test_parser(self):
+ res, ptype, _ = self.ip.parser(self.buf)
+
+ eq_(res.version, self.version)
+ eq_(res.header_length, self.header_length)
+ eq_(res.tos, self.tos)
+ eq_(res.total_length, self.total_length)
+ eq_(res.identification, self.identification)
+ eq_(res.flags, self.flags)
+ eq_(res.offset, self.offset)
+ eq_(res.ttl, self.ttl)
+ eq_(res.proto, self.proto)
+ eq_(res.csum, self.csum)
+ eq_(res.src, self.src)
+ eq_(res.dst, self.dst)
+ eq_(ptype, tcp)
+
+ def test_serialize(self):
+ buf = self.ip.serialize(bytearray(), None)
+ res = struct.unpack_from(ipv4._PACK_STR, six.binary_type(buf))
+ option = buf[ipv4._MIN_LEN:ipv4._MIN_LEN + len(self.option)]
+
+ eq_(res[0], self.ver_hlen)
+ eq_(res[1], self.tos)
+ eq_(res[2], self.total_length)
+ eq_(res[3], self.identification)
+ eq_(res[4], self.flg_off)
+ eq_(res[5], self.ttl)
+ eq_(res[6], self.proto)
+ eq_(res[8], addrconv.ipv4.text_to_bin(self.src))
+ eq_(res[9], addrconv.ipv4.text_to_bin(self.dst))
+ eq_(option, self.option)
+
+ # checksum
+ csum = packet_utils.checksum(buf)
+ eq_(csum, 0)
+
+ @raises(Exception)
+ def test_malformed_ipv4(self):
+ m_short_buf = self.buf[1:ipv4._MIN_LEN]
+ ipv4.parser(m_short_buf)
+
+ def test_json(self):
+ jsondict = self.ip.to_jsondict()
+ ip = ipv4.from_jsondict(jsondict['ipv4'])
+ eq_(str(self.ip), str(ip))
diff --git a/tests/unit/packet/test_ipv6.py b/tests/unit/packet/test_ipv6.py
new file mode 100644
index 00000000..455dc8c3
--- /dev/null
+++ b/tests/unit/packet/test_ipv6.py
@@ -0,0 +1,1128 @@
+# Copyright (C) 2013 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 unittest
+import logging
+import inspect
+import six
+import struct
+
+from nose.tools import *
+from ryu.lib import addrconv
+from ryu.lib import ip
+from ryu.lib.packet import ipv6
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_ipv6(unittest.TestCase):
+
+ def setUp(self):
+ self.version = 6
+ self.traffic_class = 0
+ self.flow_label = 0
+ self.payload_length = 817
+ self.nxt = 6
+ self.hop_limit = 128
+ self.src = '2002:4637:d5d3::4637:d5d3'
+ self.dst = '2001:4860:0:2001::68'
+ self.ext_hdrs = []
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+
+ self.v_tc_flow = (
+ self.version << 28 | self.traffic_class << 20 |
+ self.flow_label << 12)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+
+ def setUp_with_hop_opts(self):
+ self.opt1_type = 5
+ self.opt1_len = 2
+ self.opt1_data = b'\x00\x00'
+ self.opt2_type = 1
+ self.opt2_len = 0
+ self.opt2_data = None
+ self.options = [
+ ipv6.option(self.opt1_type, self.opt1_len, self.opt1_data),
+ ipv6.option(self.opt2_type, self.opt2_len, self.opt2_data),
+ ]
+ self.hop_opts_nxt = 6
+ self.hop_opts_size = 0
+ self.hop_opts = ipv6.hop_opts(
+ self.hop_opts_nxt, self.hop_opts_size, self.options)
+ self.ext_hdrs = [self.hop_opts]
+ self.payload_length += len(self.hop_opts)
+ self.nxt = ipv6.hop_opts.TYPE
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+ self.buf += self.hop_opts.serialize()
+
+ def setUp_with_dst_opts(self):
+ self.opt1_type = 5
+ self.opt1_len = 2
+ self.opt1_data = b'\x00\x00'
+ self.opt2_type = 1
+ self.opt2_len = 0
+ self.opt2_data = None
+ self.options = [
+ ipv6.option(self.opt1_type, self.opt1_len, self.opt1_data),
+ ipv6.option(self.opt2_type, self.opt2_len, self.opt2_data),
+ ]
+ self.dst_opts_nxt = 6
+ self.dst_opts_size = 0
+ self.dst_opts = ipv6.dst_opts(
+ self.dst_opts_nxt, self.dst_opts_size, self.options)
+ self.ext_hdrs = [self.dst_opts]
+ self.payload_length += len(self.dst_opts)
+ self.nxt = ipv6.dst_opts.TYPE
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+ self.buf += self.dst_opts.serialize()
+
+ def setUp_with_routing_type3(self):
+ self.routing_nxt = 6
+ self.routing_size = 6
+ self.routing_type = 3
+ self.routing_seg = 2
+ self.routing_cmpi = 0
+ self.routing_cmpe = 0
+ self.routing_adrs = ["2001:db8:dead::1", "2001:db8:dead::2",
+ "2001:db8:dead::3"]
+ self.routing = ipv6.routing_type3(
+ self.routing_nxt, self.routing_size,
+ self.routing_type, self.routing_seg,
+ self.routing_cmpi, self.routing_cmpe,
+ self.routing_adrs)
+ self.ext_hdrs = [self.routing]
+ self.payload_length += len(self.routing)
+ self.nxt = ipv6.routing.TYPE
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+ self.buf += self.routing.serialize()
+
+ def setUp_with_fragment(self):
+ self.fragment_nxt = 6
+ self.fragment_offset = 50
+ self.fragment_more = 1
+ self.fragment_id = 123
+ self.fragment = ipv6.fragment(
+ self.fragment_nxt, self.fragment_offset, self.fragment_more,
+ self.fragment_id)
+ self.ext_hdrs = [self.fragment]
+ self.payload_length += len(self.fragment)
+ self.nxt = ipv6.fragment.TYPE
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+ self.buf += self.fragment.serialize()
+
+ def setUp_with_auth(self):
+ self.auth_nxt = 6
+ self.auth_size = 4
+ self.auth_spi = 256
+ self.auth_seq = 1
+ self.auth_data = b'\xa0\xe7\xf8\xab\xf9\x69\x1a\x8b\xf3\x9f\x7c\xae'
+ self.auth = ipv6.auth(
+ self.auth_nxt, self.auth_size, self.auth_spi, self.auth_seq,
+ self.auth_data)
+ self.ext_hdrs = [self.auth]
+ self.payload_length += len(self.auth)
+ self.nxt = ipv6.auth.TYPE
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+ self.buf += self.auth.serialize()
+
+ def setUp_with_multi_headers(self):
+ self.opt1_type = 5
+ self.opt1_len = 2
+ self.opt1_data = b'\x00\x00'
+ self.opt2_type = 1
+ self.opt2_len = 0
+ self.opt2_data = None
+ self.options = [
+ ipv6.option(self.opt1_type, self.opt1_len, self.opt1_data),
+ ipv6.option(self.opt2_type, self.opt2_len, self.opt2_data),
+ ]
+ self.hop_opts_nxt = ipv6.auth.TYPE
+ self.hop_opts_size = 0
+ self.hop_opts = ipv6.hop_opts(
+ self.hop_opts_nxt, self.hop_opts_size, self.options)
+ self.auth_nxt = 6
+ self.auth_size = 4
+ self.auth_spi = 256
+ self.auth_seq = 1
+ self.auth_data = b'\xa0\xe7\xf8\xab\xf9\x69\x1a\x8b\xf3\x9f\x7c\xae'
+ self.auth = ipv6.auth(
+ self.auth_nxt, self.auth_size, self.auth_spi, self.auth_seq,
+ self.auth_data)
+ self.ext_hdrs = [self.hop_opts, self.auth]
+ self.payload_length += len(self.hop_opts) + len(self.auth)
+ self.nxt = ipv6.hop_opts.TYPE
+ self.ip = ipv6.ipv6(
+ self.version, self.traffic_class, self.flow_label,
+ self.payload_length, self.nxt, self.hop_limit, self.src,
+ self.dst, self.ext_hdrs)
+ self.buf = struct.pack(
+ ipv6.ipv6._PACK_STR, self.v_tc_flow,
+ self.payload_length, self.nxt, self.hop_limit,
+ addrconv.ipv6.text_to_bin(self.src),
+ addrconv.ipv6.text_to_bin(self.dst))
+ self.buf += self.hop_opts.serialize()
+ self.buf += self.auth.serialize()
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.version, self.ip.version)
+ eq_(self.traffic_class, self.ip.traffic_class)
+ eq_(self.flow_label, self.ip.flow_label)
+ eq_(self.payload_length, self.ip.payload_length)
+ eq_(self.nxt, self.ip.nxt)
+ eq_(self.hop_limit, self.ip.hop_limit)
+ eq_(self.src, self.ip.src)
+ eq_(self.dst, self.ip.dst)
+ eq_(str(self.ext_hdrs), str(self.ip.ext_hdrs))
+
+ def test_init_with_hop_opts(self):
+ self.setUp_with_hop_opts()
+ self.test_init()
+
+ def test_init_with_dst_opts(self):
+ self.setUp_with_dst_opts()
+ self.test_init()
+
+ def test_init_with_routing_type3(self):
+ self.setUp_with_routing_type3()
+ self.test_init()
+
+ def test_init_with_fragment(self):
+ self.setUp_with_fragment()
+ self.test_init()
+
+ def test_init_with_auth(self):
+ self.setUp_with_auth()
+ self.test_init()
+
+ def test_init_with_multi_headers(self):
+ self.setUp_with_multi_headers()
+ self.test_init()
+
+ def test_parser(self):
+ _res = self.ip.parser(six.binary_type(self.buf))
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(self.version, res.version)
+ eq_(self.traffic_class, res.traffic_class)
+ eq_(self.flow_label, res.flow_label)
+ eq_(self.payload_length, res.payload_length)
+ eq_(self.nxt, res.nxt)
+ eq_(self.hop_limit, res.hop_limit)
+ eq_(self.src, res.src)
+ eq_(self.dst, res.dst)
+ eq_(str(self.ext_hdrs), str(res.ext_hdrs))
+
+ def test_parser_with_hop_opts(self):
+ self.setUp_with_hop_opts()
+ self.test_parser()
+
+ def test_parser_with_dst_opts(self):
+ self.setUp_with_dst_opts()
+ self.test_parser()
+
+ def test_parser_with_routing_type3(self):
+ self.setUp_with_routing_type3()
+ self.test_parser()
+
+ def test_parser_with_fragment(self):
+ self.setUp_with_fragment()
+ self.test_parser()
+
+ def test_parser_with_auth(self):
+ self.setUp_with_auth()
+ self.test_parser()
+
+ def test_parser_with_multi_headers(self):
+ self.setUp_with_multi_headers()
+ self.test_parser()
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+
+ res = struct.unpack_from(ipv6.ipv6._PACK_STR, six.binary_type(buf))
+
+ eq_(self.v_tc_flow, res[0])
+ eq_(self.payload_length, res[1])
+ eq_(self.nxt, res[2])
+ eq_(self.hop_limit, res[3])
+ eq_(self.src, addrconv.ipv6.bin_to_text(res[4]))
+ eq_(self.dst, addrconv.ipv6.bin_to_text(res[5]))
+
+ def test_serialize_with_hop_opts(self):
+ self.setUp_with_hop_opts()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+ hop_opts = ipv6.hop_opts.parser(six.binary_type(buf[ipv6.ipv6._MIN_LEN:]))
+ eq_(repr(self.hop_opts), repr(hop_opts))
+
+ def test_serialize_with_dst_opts(self):
+ self.setUp_with_dst_opts()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+ dst_opts = ipv6.dst_opts.parser(six.binary_type(buf[ipv6.ipv6._MIN_LEN:]))
+ eq_(repr(self.dst_opts), repr(dst_opts))
+
+ def test_serialize_with_routing_type3(self):
+ self.setUp_with_routing_type3()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+ routing = ipv6.routing.parser(six.binary_type(buf[ipv6.ipv6._MIN_LEN:]))
+ eq_(repr(self.routing), repr(routing))
+
+ def test_serialize_with_fragment(self):
+ self.setUp_with_fragment()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+ fragment = ipv6.fragment.parser(six.binary_type(buf[ipv6.ipv6._MIN_LEN:]))
+ eq_(repr(self.fragment), repr(fragment))
+
+ def test_serialize_with_auth(self):
+ self.setUp_with_auth()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+ auth = ipv6.auth.parser(six.binary_type(buf[ipv6.ipv6._MIN_LEN:]))
+ eq_(repr(self.auth), repr(auth))
+
+ def test_serialize_with_multi_headers(self):
+ self.setUp_with_multi_headers()
+ self.test_serialize()
+
+ data = bytearray()
+ prev = None
+ buf = self.ip.serialize(data, prev)
+ offset = ipv6.ipv6._MIN_LEN
+ hop_opts = ipv6.hop_opts.parser(six.binary_type(buf[offset:]))
+ offset += len(hop_opts)
+ auth = ipv6.auth.parser(six.binary_type(buf[offset:]))
+ eq_(repr(self.hop_opts), repr(hop_opts))
+ eq_(repr(self.auth), repr(auth))
+
+ def test_to_string(self):
+ ipv6_values = {'version': self.version,
+ 'traffic_class': self.traffic_class,
+ 'flow_label': self.flow_label,
+ 'payload_length': self.payload_length,
+ 'nxt': self.nxt,
+ 'hop_limit': self.hop_limit,
+ 'src': repr(self.src),
+ 'dst': repr(self.dst),
+ 'ext_hdrs': self.ext_hdrs}
+ _ipv6_str = ','.join(['%s=%s' % (k, ipv6_values[k])
+ for k, v in inspect.getmembers(self.ip)
+ if k in ipv6_values])
+ ipv6_str = '%s(%s)' % (ipv6.ipv6.__name__, _ipv6_str)
+
+ eq_(str(self.ip), ipv6_str)
+ eq_(repr(self.ip), ipv6_str)
+
+ def test_to_string_with_hop_opts(self):
+ self.setUp_with_hop_opts()
+ self.test_to_string()
+
+ def test_to_string_with_dst_opts(self):
+ self.setUp_with_dst_opts()
+ self.test_to_string()
+
+ def test_to_string_with_fragment(self):
+ self.setUp_with_fragment()
+ self.test_to_string()
+
+ def test_to_string_with_auth(self):
+ self.setUp_with_auth()
+ self.test_to_string()
+
+ def test_to_string_with_multi_headers(self):
+ self.setUp_with_multi_headers()
+ self.test_to_string()
+
+ def test_len(self):
+ eq_(len(self.ip), 40)
+
+ def test_len_with_hop_opts(self):
+ self.setUp_with_hop_opts()
+ eq_(len(self.ip), 40 + len(self.hop_opts))
+
+ def test_len_with_dst_opts(self):
+ self.setUp_with_dst_opts()
+ eq_(len(self.ip), 40 + len(self.dst_opts))
+
+ def test_len_with_routing_type3(self):
+ self.setUp_with_routing_type3()
+ eq_(len(self.ip), 40 + len(self.routing))
+
+ def test_len_with_fragment(self):
+ self.setUp_with_fragment()
+ eq_(len(self.ip), 40 + len(self.fragment))
+
+ def test_len_with_auth(self):
+ self.setUp_with_auth()
+ eq_(len(self.ip), 40 + len(self.auth))
+
+ def test_len_with_multi_headers(self):
+ self.setUp_with_multi_headers()
+ eq_(len(self.ip), 40 + len(self.hop_opts) + len(self.auth))
+
+ def test_default_args(self):
+ ip = ipv6.ipv6()
+ buf = ip.serialize(bytearray(), None)
+ res = struct.unpack(ipv6.ipv6._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], 6 << 28)
+ eq_(res[1], 0)
+ eq_(res[2], 6)
+ eq_(res[3], 255)
+ eq_(res[4], addrconv.ipv6.text_to_bin('10::10'))
+ eq_(res[5], addrconv.ipv6.text_to_bin('20::20'))
+
+ # with extension header
+ ip = ipv6.ipv6(
+ nxt=0, ext_hdrs=[
+ ipv6.hop_opts(58, 0, [
+ ipv6.option(5, 2, b'\x00\x00'),
+ ipv6.option(1, 0, None)])])
+ buf = ip.serialize(bytearray(), None)
+ res = struct.unpack(ipv6.ipv6._PACK_STR + '8s', six.binary_type(buf))
+
+ eq_(res[0], 6 << 28)
+ eq_(res[1], 8)
+ eq_(res[2], 0)
+ eq_(res[3], 255)
+ eq_(res[4], addrconv.ipv6.text_to_bin('10::10'))
+ eq_(res[5], addrconv.ipv6.text_to_bin('20::20'))
+ eq_(res[6], b'\x3a\x00\x05\x02\x00\x00\x01\x00')
+
+ def test_json(self):
+ jsondict = self.ip.to_jsondict()
+ ip = ipv6.ipv6.from_jsondict(jsondict['ipv6'])
+ eq_(str(self.ip), str(ip))
+
+ def test_json_with_hop_opts(self):
+ self.setUp_with_hop_opts()
+ self.test_json()
+
+ def test_json_with_dst_opts(self):
+ self.setUp_with_dst_opts()
+ self.test_json()
+
+ def test_json_with_routing_type3(self):
+ self.setUp_with_routing_type3()
+ self.test_json()
+
+ def test_json_with_fragment(self):
+ self.setUp_with_fragment()
+ self.test_json()
+
+ def test_json_with_auth(self):
+ self.setUp_with_auth()
+ self.test_json()
+
+ def test_json_with_multi_headers(self):
+ self.setUp_with_multi_headers()
+ self.test_json()
+
+
+class Test_hop_opts(unittest.TestCase):
+
+ def setUp(self):
+ self.nxt = 0
+ self.size = 8
+ self.data = [
+ ipv6.option(5, 2, b'\x00\x00'),
+ ipv6.option(1, 0, None),
+ ipv6.option(0xc2, 4, b'\x00\x01\x00\x00'),
+ ipv6.option(1, 0, None),
+ ]
+ self.hop = ipv6.hop_opts(self.nxt, self.size, self.data)
+ self.form = '!BB'
+ self.buf = struct.pack(self.form, self.nxt, self.size) \
+ + self.data[0].serialize() \
+ + self.data[1].serialize() \
+ + self.data[2].serialize() \
+ + self.data[3].serialize()
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.nxt, self.hop.nxt)
+ eq_(self.size, self.hop.size)
+ eq_(self.data, self.hop.data)
+
+ @raises(Exception)
+ def test_invalid_size(self):
+ ipv6.hop_opts(self.nxt, 1, self.data)
+
+ def test_parser(self):
+ _res = ipv6.hop_opts.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.nxt, res.nxt)
+ eq_(self.size, res.size)
+ eq_(str(self.data), str(res.data))
+
+ def test_serialize(self):
+ buf = self.hop.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.nxt, res[0])
+ eq_(self.size, res[1])
+ offset = struct.calcsize(self.form)
+ opt1 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ offset += len(opt1)
+ opt2 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ offset += len(opt2)
+ opt3 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ offset += len(opt3)
+ opt4 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ eq_(5, opt1.type_)
+ eq_(2, opt1.len_)
+ eq_(b'\x00\x00', opt1.data)
+ eq_(1, opt2.type_)
+ eq_(0, opt2.len_)
+ eq_(None, opt2.data)
+ eq_(0xc2, opt3.type_)
+ eq_(4, opt3.len_)
+ eq_(b'\x00\x01\x00\x00', opt3.data)
+ eq_(1, opt4.type_)
+ eq_(0, opt4.len_)
+ eq_(None, opt4.data)
+
+ def test_len(self):
+ eq_(16, len(self.hop))
+
+ def test_default_args(self):
+ hdr = ipv6.hop_opts()
+ buf = hdr.serialize()
+ res = struct.unpack('!BB', six.binary_type(buf[:2]))
+
+ eq_(res[0], 6)
+ eq_(res[1], 0)
+ opt = ipv6.option(type_=1, len_=4, data=b'\x00\x00\x00\x00')
+ eq_(six.binary_type(buf[2:]), opt.serialize())
+
+
+class Test_dst_opts(unittest.TestCase):
+
+ def setUp(self):
+ self.nxt = 60
+ self.size = 8
+ self.data = [
+ ipv6.option(5, 2, b'\x00\x00'),
+ ipv6.option(1, 0, None),
+ ipv6.option(0xc2, 4, b'\x00\x01\x00\x00'),
+ ipv6.option(1, 0, None),
+ ]
+ self.dst = ipv6.dst_opts(self.nxt, self.size, self.data)
+ self.form = '!BB'
+ self.buf = struct.pack(self.form, self.nxt, self.size) \
+ + self.data[0].serialize() \
+ + self.data[1].serialize() \
+ + self.data[2].serialize() \
+ + self.data[3].serialize()
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.nxt, self.dst.nxt)
+ eq_(self.size, self.dst.size)
+ eq_(self.data, self.dst.data)
+
+ @raises(Exception)
+ def test_invalid_size(self):
+ ipv6.dst_opts(self.nxt, 1, self.data)
+
+ def test_parser(self):
+ _res = ipv6.dst_opts.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.nxt, res.nxt)
+ eq_(self.size, res.size)
+ eq_(str(self.data), str(res.data))
+
+ def test_serialize(self):
+ buf = self.dst.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.nxt, res[0])
+ eq_(self.size, res[1])
+ offset = struct.calcsize(self.form)
+ opt1 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ offset += len(opt1)
+ opt2 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ offset += len(opt2)
+ opt3 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ offset += len(opt3)
+ opt4 = ipv6.option.parser(six.binary_type(buf[offset:]))
+ eq_(5, opt1.type_)
+ eq_(2, opt1.len_)
+ eq_(b'\x00\x00', opt1.data)
+ eq_(1, opt2.type_)
+ eq_(0, opt2.len_)
+ eq_(None, opt2.data)
+ eq_(0xc2, opt3.type_)
+ eq_(4, opt3.len_)
+ eq_(b'\x00\x01\x00\x00', opt3.data)
+ eq_(1, opt4.type_)
+ eq_(0, opt4.len_)
+ eq_(None, opt4.data)
+
+ def test_len(self):
+ eq_(16, len(self.dst))
+
+ def test_default_args(self):
+ hdr = ipv6.dst_opts()
+ buf = hdr.serialize()
+ res = struct.unpack('!BB', six.binary_type(buf[:2]))
+
+ eq_(res[0], 6)
+ eq_(res[1], 0)
+ opt = ipv6.option(type_=1, len_=4, data=b'\x00\x00\x00\x00')
+ eq_(six.binary_type(buf[2:]), opt.serialize())
+
+
+class Test_option(unittest.TestCase):
+
+ def setUp(self):
+ self.type_ = 5
+ self.data = b'\x00\x00'
+ self.len_ = len(self.data)
+ self.opt = ipv6.option(self.type_, self.len_, self.data)
+ self.form = '!BB%ds' % self.len_
+ self.buf = struct.pack(self.form, self.type_, self.len_, self.data)
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.type_, self.opt.type_)
+ eq_(self.len_, self.opt.len_)
+ eq_(self.data, self.opt.data)
+
+ def test_parser(self):
+ _res = ipv6.option.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.type_, res.type_)
+ eq_(self.len_, res.len_)
+ eq_(self.data, res.data)
+
+ def test_serialize(self):
+ buf = self.opt.serialize()
+ res = struct.unpack_from(self.form, buf)
+ eq_(self.type_, res[0])
+ eq_(self.len_, res[1])
+ eq_(self.data, res[2])
+
+ def test_len(self):
+ eq_(len(self.opt), 2 + self.len_)
+
+
+class Test_option_pad1(Test_option):
+
+ def setUp(self):
+ self.type_ = 0
+ self.len_ = -1
+ self.data = None
+ self.opt = ipv6.option(self.type_, self.len_, self.data)
+ self.form = '!B'
+ self.buf = struct.pack(self.form, self.type_)
+
+ def test_serialize(self):
+ buf = self.opt.serialize()
+ res = struct.unpack_from(self.form, buf)
+ eq_(self.type_, res[0])
+
+ def test_default_args(self):
+ opt = ipv6.option()
+ buf = opt.serialize()
+ res = struct.unpack('!B', buf)
+
+ eq_(res[0], 0)
+
+
+class Test_option_padN(Test_option):
+
+ def setUp(self):
+ self.type_ = 1
+ self.len_ = 0
+ self.data = None
+ self.opt = ipv6.option(self.type_, self.len_, self.data)
+ self.form = '!BB'
+ self.buf = struct.pack(self.form, self.type_, self.len_)
+
+ def test_serialize(self):
+ buf = self.opt.serialize()
+ res = struct.unpack_from(self.form, buf)
+ eq_(self.type_, res[0])
+ eq_(self.len_, res[1])
+
+
+class Test_routing(unittest.TestCase):
+
+ def setUp(self):
+ self.nxt = 0
+ self.size = 6
+ self.type_ = ipv6.routing.ROUTING_TYPE_3
+ self.seg = 0
+ self.cmpi = 0
+ self.cmpe = 0
+ self.adrs = ["2001:db8:dead::1",
+ "2001:db8:dead::2",
+ "2001:db8:dead::3"]
+ # calculate pad
+ self.pad = (8 - ((len(self.adrs) - 1) * (16 - self.cmpi) +
+ (16 - self.cmpe) % 8)) % 8
+ # create buf
+ self.form = '!BBBBBB2x16s16s16s'
+ self.buf = struct.pack(self.form, self.nxt, self.size,
+ self.type_, self.seg,
+ (self.cmpi << 4) | self.cmpe,
+ self.pad << 4,
+ addrconv.ipv6.text_to_bin(self.adrs[0]),
+ addrconv.ipv6.text_to_bin(self.adrs[1]),
+ addrconv.ipv6.text_to_bin(self.adrs[2]))
+
+ def tearDown(self):
+ pass
+
+ def test_parser(self):
+ _res = ipv6.routing.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.nxt, res.nxt)
+ eq_(self.size, res.size)
+ eq_(self.type_, res.type_)
+ eq_(self.seg, res.seg)
+ eq_(self.cmpi, res.cmpi)
+ eq_(self.cmpe, res.cmpe)
+ eq_(self.pad, res._pad)
+ eq_(self.adrs[0], res.adrs[0])
+ eq_(self.adrs[1], res.adrs[1])
+ eq_(self.adrs[2], res.adrs[2])
+
+ def test_not_implemented_type(self):
+ not_implemented_buf = struct.pack(
+ '!BBBBBB2x', 0, 6, ipv6.routing.ROUTING_TYPE_2, 0, 0, 0)
+ instance = ipv6.routing.parser(not_implemented_buf)
+ assert None == instance
+
+ def test_invalid_type(self):
+ invalid_type = 99
+ invalid_buf = struct.pack('!BBBBBB2x', 0, 6, invalid_type, 0, 0, 0)
+ instance = ipv6.routing.parser(invalid_buf)
+ assert None == instance
+
+
+class Test_routing_type3(unittest.TestCase):
+
+ def setUp(self):
+ self.nxt = 0
+ self.size = 6
+ self.type_ = 3
+ self.seg = 0
+ self.cmpi = 0
+ self.cmpe = 0
+ self.adrs = ["2001:db8:dead::1",
+ "2001:db8:dead::2",
+ "2001:db8:dead::3"]
+ # calculate pad
+ self.pad = (8 - ((len(self.adrs) - 1) * (16 - self.cmpi) +
+ (16 - self.cmpe) % 8)) % 8
+
+ self.routing = ipv6.routing_type3(
+ self.nxt, self.size, self.type_, self.seg, self.cmpi,
+ self.cmpe, self.adrs)
+ self.form = '!BBBBBB2x16s16s16s'
+ self.buf = struct.pack(self.form, self.nxt, self.size,
+ self.type_, self.seg,
+ (self.cmpi << 4) | self.cmpe,
+ self.pad << 4,
+ addrconv.ipv6.text_to_bin(self.adrs[0]),
+ addrconv.ipv6.text_to_bin(self.adrs[1]),
+ addrconv.ipv6.text_to_bin(self.adrs[2]))
+
+ def test_init(self):
+ eq_(self.nxt, self.routing.nxt)
+ eq_(self.size, self.routing.size)
+ eq_(self.type_, self.routing.type_)
+ eq_(self.seg, self.routing.seg)
+ eq_(self.cmpi, self.routing.cmpi)
+ eq_(self.cmpe, self.routing.cmpe)
+ eq_(self.pad, self.routing._pad)
+ eq_(self.adrs[0], self.routing.adrs[0])
+ eq_(self.adrs[1], self.routing.adrs[1])
+ eq_(self.adrs[2], self.routing.adrs[2])
+
+ def test_parser(self):
+ _res = ipv6.routing.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.nxt, res.nxt)
+ eq_(self.size, res.size)
+ eq_(self.type_, res.type_)
+ eq_(self.seg, res.seg)
+ eq_(self.cmpi, res.cmpi)
+ eq_(self.cmpe, res.cmpe)
+ eq_(self.pad, res._pad)
+ eq_(self.adrs[0], res.adrs[0])
+ eq_(self.adrs[1], res.adrs[1])
+ eq_(self.adrs[2], res.adrs[2])
+
+ def test_serialize(self):
+ buf = self.routing.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.nxt, res[0])
+ eq_(self.size, res[1])
+ eq_(self.type_, res[2])
+ eq_(self.seg, res[3])
+ eq_(self.cmpi, res[4] >> 4)
+ eq_(self.cmpe, res[4] & 0xf)
+ eq_(self.pad, res[5])
+ eq_(addrconv.ipv6.text_to_bin(self.adrs[0]), res[6])
+ eq_(addrconv.ipv6.text_to_bin(self.adrs[1]), res[7])
+ eq_(addrconv.ipv6.text_to_bin(self.adrs[2]), res[8])
+
+ def test_parser_with_adrs_zero(self):
+ nxt = 0
+ size = 0
+ type_ = 3
+ seg = 0
+ cmpi = 0
+ cmpe = 0
+ adrs = []
+ # calculate pad
+ pad = (8 - ((len(adrs) - 1) * (16 - cmpi) + (16 - cmpe) % 8)) % 8
+
+ form = '!BBBBBB2x'
+ buf = struct.pack(form, nxt, size, type_, seg,
+ (cmpi << 4) | cmpe, pad << 4)
+ _res = ipv6.routing.parser(buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(nxt, res.nxt)
+ eq_(size, res.size)
+ eq_(type_, res.type_)
+ eq_(seg, res.seg)
+ eq_(cmpi, res.cmpi)
+ eq_(cmpe, res.cmpe)
+ eq_(pad, res._pad)
+
+ def test_serialize_with_adrs_zero(self):
+ nxt = 0
+ size = 0
+ type_ = 3
+ seg = 0
+ cmpi = 0
+ cmpe = 0
+ adrs = []
+ # calculate pad
+ pad = (8 - ((len(adrs) - 1) * (16 - cmpi) + (16 - cmpe) % 8)) % 8
+ routing = ipv6.routing_type3(
+ nxt, size, type_, seg, cmpi,
+ cmpe, pad)
+ buf = routing.serialize()
+ form = '!BBBBBB2x'
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(nxt, res[0])
+ eq_(size, res[1])
+ eq_(type_, res[2])
+ eq_(seg, res[3])
+ eq_(cmpi, res[4] >> 4)
+ eq_(cmpe, res[4] & 0xf)
+ eq_(pad, res[5])
+
+ def test_parser_with_compression(self):
+ pass
+ nxt = 0
+ size = 3
+ type_ = 3
+ seg = 0
+ cmpi = 8
+ cmpe = 12
+ adrs = ["2001:0db8:dead:0123:4567:89ab:cdef:0001",
+ "2001:0db8:dead:0123:4567:89ab:cdef:0002",
+ "2001:0db8:dead:0123:4567:89ab:cdef:0003"]
+ # calculate pad
+ pad = (8 - ((len(adrs) - 1) * (16 - cmpi) + (16 - cmpe) % 8)) % 8
+ form = '!BBBBBB2x%ds%ds%ds' % (16 - cmpi, 16 - cmpi, 16 - cmpe)
+ slice_i = slice(cmpi, 16)
+ slice_e = slice(cmpe, 16)
+ buf = struct.pack(form, nxt, size, type_, seg,
+ (cmpi << 4) | cmpe, pad << 4,
+ addrconv.ipv6.text_to_bin(adrs[0])[slice_i],
+ addrconv.ipv6.text_to_bin(adrs[1])[slice_i],
+ addrconv.ipv6.text_to_bin(adrs[2])[slice_e])
+ _res = ipv6.routing.parser(buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(nxt, res.nxt)
+ eq_(size, res.size)
+ eq_(type_, res.type_)
+ eq_(seg, res.seg)
+ eq_(cmpi, res.cmpi)
+ eq_(cmpe, res.cmpe)
+ eq_(pad, res._pad)
+ eq_("::4567:89ab:cdef:1", res.adrs[0])
+ eq_("::4567:89ab:cdef:2", res.adrs[1])
+ eq_("::205.239.0.3", res.adrs[2])
+
+ def test_serialize_with_compression(self):
+ nxt = 0
+ size = 3
+ type_ = 3
+ seg = 0
+ cmpi = 8
+ cmpe = 8
+ adrs = ["2001:db8:dead::1",
+ "2001:db8:dead::2",
+ "2001:db8:dead::3"]
+ # calculate pad
+ pad = (8 - ((len(adrs) - 1) * (16 - cmpi) + (16 - cmpe) % 8)) % 8
+ slice_i = slice(cmpi, 16)
+ slice_e = slice(cmpe, 16)
+ routing = ipv6.routing_type3(
+ nxt, size, type_, seg, cmpi, cmpe, adrs)
+ buf = routing.serialize()
+ form = '!BBBBBB2x8s8s8s'
+ res = struct.unpack_from(form, six.binary_type(buf))
+ eq_(nxt, res[0])
+ eq_(size, res[1])
+ eq_(type_, res[2])
+ eq_(seg, res[3])
+ eq_(cmpi, res[4] >> 4)
+ eq_(cmpe, res[4] & 0xf)
+ eq_(pad, res[5])
+ eq_(addrconv.ipv6.text_to_bin(adrs[0])[slice_i], res[6])
+ eq_(addrconv.ipv6.text_to_bin(adrs[1])[slice_i], res[7])
+ eq_(addrconv.ipv6.text_to_bin(adrs[2])[slice_e], res[8])
+
+ def test_len(self):
+ eq_((6 + 1) * 8, len(self.routing))
+
+ def test_default_args(self):
+ hdr = ipv6.routing_type3()
+ buf = hdr.serialize()
+ LOG.info(repr(buf))
+ res = struct.unpack_from(ipv6.routing_type3._PACK_STR, six.binary_type(buf))
+ LOG.info(res)
+
+ eq_(res[0], 6)
+ eq_(res[1], 0)
+ eq_(res[2], 3)
+ eq_(res[3], 0)
+ eq_(res[4], (0 << 4) | 0)
+ eq_(res[5], 0)
+
+
+class Test_fragment(unittest.TestCase):
+
+ def setUp(self):
+ self.nxt = 44
+ self.offset = 50
+ self.more = 1
+ self.id_ = 123
+ self.fragment = ipv6.fragment(
+ self.nxt, self.offset, self.more, self.id_)
+
+ self.off_m = (self.offset << 3 | self.more)
+ self.form = '!BxHI'
+ self.buf = struct.pack(self.form, self.nxt, self.off_m, self.id_)
+
+ def test_init(self):
+ eq_(self.nxt, self.fragment.nxt)
+ eq_(self.offset, self.fragment.offset)
+ eq_(self.more, self.fragment.more)
+ eq_(self.id_, self.fragment.id_)
+
+ def test_parser(self):
+ _res = ipv6.fragment.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.nxt, res.nxt)
+ eq_(self.offset, res.offset)
+ eq_(self.more, res.more)
+ eq_(self.id_, res.id_)
+
+ def test_serialize(self):
+ buf = self.fragment.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.nxt, res[0])
+ eq_(self.off_m, res[1])
+ eq_(self.id_, res[2])
+
+ def test_len(self):
+ eq_(8, len(self.fragment))
+
+ def test_default_args(self):
+ hdr = ipv6.fragment()
+ buf = hdr.serialize()
+ res = struct.unpack_from(ipv6.fragment._PACK_STR, buf)
+
+ eq_(res[0], 6)
+ eq_(res[1], 0)
+ eq_(res[2], 0)
+
+
+class Test_auth(unittest.TestCase):
+
+ def setUp(self):
+ self.nxt = 0
+ self.size = 4
+ self.spi = 256
+ self.seq = 1
+ self.data = b'\x21\xd3\xa9\x5c\x5f\xfd\x4d\x18\x46\x22\xb9\xf8'
+ self.auth = ipv6.auth(
+ self.nxt, self.size, self.spi, self.seq, self.data)
+ self.form = '!BB2xII12s'
+ self.buf = struct.pack(self.form, self.nxt, self.size, self.spi,
+ self.seq, self.data)
+
+ def test_init(self):
+ eq_(self.nxt, self.auth.nxt)
+ eq_(self.size, self.auth.size)
+ eq_(self.spi, self.auth.spi)
+ eq_(self.seq, self.auth.seq)
+ eq_(self.data, self.auth.data)
+
+ def test_parser(self):
+ _res = ipv6.auth.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(self.nxt, res.nxt)
+ eq_(self.size, res.size)
+ eq_(self.spi, res.spi)
+ eq_(self.seq, res.seq)
+ eq_(self.data, res.data)
+
+ def test_serialize(self):
+ buf = self.auth.serialize()
+ res = struct.unpack_from(self.form, six.binary_type(buf))
+ eq_(self.nxt, res[0])
+ eq_(self.size, res[1])
+ eq_(self.spi, res[2])
+ eq_(self.seq, res[3])
+ eq_(self.data, res[4])
+
+ def test_len(self):
+ eq_((4 + 2) * 4, len(self.auth))
+
+ def test_len_re(self):
+ size = 5
+ auth = ipv6.auth(
+ 0, size, 256, 1,
+ b'\x21\xd3\xa9\x5c\x5f\xfd\x4d\x18\x46\x22\xb9\xf8\xf8\xf8\xf8\xf8')
+ eq_((size + 2) * 4, len(auth))
+
+ def test_default_args(self):
+ hdr = ipv6.auth()
+ buf = hdr.serialize()
+ LOG.info(repr(buf))
+ res = struct.unpack_from(ipv6.auth._PACK_STR, six.binary_type(buf))
+ LOG.info(res)
+
+ eq_(res[0], 6)
+ eq_(res[1], 2)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(buf[ipv6.auth._MIN_LEN:], b'\x00\x00\x00\x00')
diff --git a/tests/unit/packet/test_llc.py b/tests/unit/packet/test_llc.py
new file mode 100644
index 00000000..05894ab7
--- /dev/null
+++ b/tests/unit/packet/test_llc.py
@@ -0,0 +1,42 @@
+# Copyright (C) 2013 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 unittest
+import logging
+
+from nose.tools import eq_
+from ryu.lib.packet import llc
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_ControlFormatI(unittest.TestCase):
+ msg = llc.llc(llc.SAP_BPDU, llc.SAP_BPDU, llc.ControlFormatI())
+
+ def test_json(self):
+ jsondict = self.msg.to_jsondict()
+ msg = llc.llc.from_jsondict(jsondict['llc'])
+ eq_(str(self.msg), str(msg))
+
+
+class Test_ControlFormatS(Test_ControlFormatI):
+ msg = llc.llc(llc.SAP_BPDU, llc.SAP_BPDU, llc.ControlFormatS())
+
+
+class Test_ControlFormatU(Test_ControlFormatI):
+ msg = llc.llc(llc.SAP_BPDU, llc.SAP_BPDU, llc.ControlFormatU())
diff --git a/tests/unit/packet/test_lldp.py b/tests/unit/packet/test_lldp.py
new file mode 100644
index 00000000..d8d261c2
--- /dev/null
+++ b/tests/unit/packet/test_lldp.py
@@ -0,0 +1,533 @@
+# Copyright (C) 2013 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 unittest
+import logging
+import six
+import struct
+import inspect
+from nose.tools import ok_, eq_, nottest
+
+from ryu.ofproto import ether
+from ryu.lib.packet import packet
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import lldp
+from ryu.lib import addrconv
+
+LOG = logging.getLogger(__name__)
+
+
+class TestLLDPMandatoryTLV(unittest.TestCase):
+ def setUp(self):
+ # sample data is based on:
+ # http://wiki.wireshark.org/LinkLayerDiscoveryProtocol
+ #
+ # mandatory TLV only
+ self.data = b'\x01\x80\xc2\x00\x00\x0e\x00\x04' \
+ + b'\x96\x1f\xa7\x26\x88\xcc\x02\x07' \
+ + b'\x04\x00\x04\x96\x1f\xa7\x26\x04' \
+ + b'\x04\x05\x31\x2f\x33\x06\x02\x00' \
+ + b'\x78\x00\x00'
+
+ def tearDown(self):
+ pass
+
+ def test_get_tlv_type(self):
+ buf = b'\x02\x07\x04\x00\x04\x96\x1f\xa7\x26'
+ eq_(lldp.LLDPBasicTLV.get_type(buf), lldp.LLDP_TLV_CHASSIS_ID)
+
+ def test_parse_without_ethernet(self):
+ buf = self.data[ethernet.ethernet._MIN_LEN:]
+ (lldp_pkt, cls, rest_buf) = lldp.lldp.parser(buf)
+ eq_(len(rest_buf), 0)
+
+ tlvs = lldp_pkt.tlvs
+ eq_(tlvs[0].tlv_type, lldp.LLDP_TLV_CHASSIS_ID)
+ eq_(tlvs[0].len, 7)
+ eq_(tlvs[0].subtype, lldp.ChassisID.SUB_MAC_ADDRESS)
+ eq_(tlvs[0].chassis_id, b'\x00\x04\x96\x1f\xa7\x26')
+ eq_(tlvs[1].tlv_type, lldp.LLDP_TLV_PORT_ID)
+ eq_(tlvs[1].len, 4)
+ eq_(tlvs[1].subtype, lldp.PortID.SUB_INTERFACE_NAME)
+ eq_(tlvs[1].port_id, b'1/3')
+ eq_(tlvs[2].tlv_type, lldp.LLDP_TLV_TTL)
+ eq_(tlvs[2].len, 2)
+ eq_(tlvs[2].ttl, 120)
+ eq_(tlvs[3].tlv_type, lldp.LLDP_TLV_END)
+
+ def test_parse(self):
+ buf = self.data
+ pkt = packet.Packet(buf)
+ i = iter(pkt)
+
+ eq_(type(next(i)), ethernet.ethernet)
+ eq_(type(next(i)), lldp.lldp)
+
+ def test_tlv(self):
+ tlv = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=b'\x00\x04\x96\x1f\xa7\x26')
+ eq_(tlv.tlv_type, lldp.LLDP_TLV_CHASSIS_ID)
+ eq_(tlv.len, 7)
+ (typelen, ) = struct.unpack('!H', b'\x02\x07')
+ eq_(tlv.typelen, typelen)
+
+ def test_serialize_without_ethernet(self):
+ tlv_chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=b'\x00\x04\x96\x1f\xa7\x26')
+ tlv_port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/3')
+ tlv_ttl = lldp.TTL(ttl=120)
+ tlv_end = lldp.End()
+ tlvs = (tlv_chassis_id, tlv_port_id, tlv_ttl, tlv_end)
+ lldp_pkt = lldp.lldp(tlvs)
+
+ eq_(lldp_pkt.serialize(None, None),
+ self.data[ethernet.ethernet._MIN_LEN:])
+
+ def test_serialize(self):
+ pkt = packet.Packet()
+
+ dst = lldp.LLDP_MAC_NEAREST_BRIDGE
+ src = '00:04:96:1f:a7:26'
+ ethertype = ether.ETH_TYPE_LLDP
+ eth_pkt = ethernet.ethernet(dst, src, ethertype)
+ pkt.add_protocol(eth_pkt)
+
+ tlv_chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=addrconv.mac.
+ text_to_bin(src))
+ tlv_port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/3')
+ tlv_ttl = lldp.TTL(ttl=120)
+ tlv_end = lldp.End()
+ tlvs = (tlv_chassis_id, tlv_port_id, tlv_ttl, tlv_end)
+ lldp_pkt = lldp.lldp(tlvs)
+ pkt.add_protocol(lldp_pkt)
+
+ eq_(len(pkt.protocols), 2)
+
+ pkt.serialize()
+
+ # Note: If ethernet frame is less than 60 bytes length,
+ # ethernet.ethernet() appends padding to the payload.
+ # So, we splits the serialized data to compare.
+ data_len = len(self.data)
+ pkt_data_lldp = pkt.data[:data_len]
+ pkt_data_pad = pkt.data[data_len:]
+ eq_(b'\x00' * (60 - data_len), pkt_data_pad)
+
+ eq_(self.data, pkt_data_lldp)
+
+ def test_to_string(self):
+ chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=b'\x00\x04\x96\x1f\xa7\x26')
+ port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/3')
+ ttl = lldp.TTL(ttl=120)
+ end = lldp.End()
+ tlvs = (chassis_id, port_id, ttl, end)
+ lldp_pkt = lldp.lldp(tlvs)
+
+ chassis_id_values = {'subtype': lldp.ChassisID.SUB_MAC_ADDRESS,
+ 'chassis_id': b'\x00\x04\x96\x1f\xa7\x26',
+ 'len': chassis_id.len,
+ 'typelen': chassis_id.typelen}
+ _ch_id_str = ','.join(['%s=%s' % (k, repr(chassis_id_values[k]))
+ for k, v in inspect.getmembers(chassis_id)
+ if k in chassis_id_values])
+ tlv_chassis_id_str = '%s(%s)' % (lldp.ChassisID.__name__, _ch_id_str)
+
+ port_id_values = {'subtype': port_id.subtype,
+ 'port_id': port_id.port_id,
+ 'len': port_id.len,
+ 'typelen': port_id.typelen}
+ _port_id_str = ','.join(['%s=%s' % (k, repr(port_id_values[k]))
+ for k, v in inspect.getmembers(port_id)
+ if k in port_id_values])
+ tlv_port_id_str = '%s(%s)' % (lldp.PortID.__name__, _port_id_str)
+
+ ttl_values = {'ttl': ttl.ttl,
+ 'len': ttl.len,
+ 'typelen': ttl.typelen}
+ _ttl_str = ','.join(['%s=%s' % (k, repr(ttl_values[k]))
+ for k, v in inspect.getmembers(ttl)
+ if k in ttl_values])
+ tlv_ttl_str = '%s(%s)' % (lldp.TTL.__name__, _ttl_str)
+
+ end_values = {'len': end.len,
+ 'typelen': end.typelen}
+ _end_str = ','.join(['%s=%s' % (k, repr(end_values[k]))
+ for k, v in inspect.getmembers(end)
+ if k in end_values])
+ tlv_end_str = '%s(%s)' % (lldp.End.__name__, _end_str)
+
+ _tlvs_str = '(%s, %s, %s, %s)'
+ tlvs_str = _tlvs_str % (tlv_chassis_id_str,
+ tlv_port_id_str,
+ tlv_ttl_str,
+ tlv_end_str)
+
+ _lldp_str = '%s(tlvs=%s)'
+ lldp_str = _lldp_str % (lldp.lldp.__name__,
+ tlvs_str)
+
+ eq_(str(lldp_pkt), lldp_str)
+ eq_(repr(lldp_pkt), lldp_str)
+
+ def test_json(self):
+ chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=b'\x00\x04\x96\x1f\xa7\x26')
+ port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/3')
+ ttl = lldp.TTL(ttl=120)
+ end = lldp.End()
+ tlvs = (chassis_id, port_id, ttl, end)
+ lldp1 = lldp.lldp(tlvs)
+ jsondict = lldp1.to_jsondict()
+ lldp2 = lldp.lldp.from_jsondict(jsondict['lldp'])
+ eq_(str(lldp1), str(lldp2))
+
+
+class TestLLDPOptionalTLV(unittest.TestCase):
+ def setUp(self):
+ # sample data is based on:
+ # http://wiki.wireshark.org/LinkLayerDiscoveryProtocol
+ #
+ # include optional TLV
+ self.data = b'\x01\x80\xc2\x00\x00\x0e\x00\x01' \
+ + b'\x30\xf9\xad\xa0\x88\xcc\x02\x07' \
+ + b'\x04\x00\x01\x30\xf9\xad\xa0\x04' \
+ + b'\x04\x05\x31\x2f\x31\x06\x02\x00' \
+ + b'\x78\x08\x17\x53\x75\x6d\x6d\x69' \
+ + b'\x74\x33\x30\x30\x2d\x34\x38\x2d' \
+ + b'\x50\x6f\x72\x74\x20\x31\x30\x30' \
+ + b'\x31\x00\x0a\x0d\x53\x75\x6d\x6d' \
+ + b'\x69\x74\x33\x30\x30\x2d\x34\x38' \
+ + b'\x00\x0c\x4c\x53\x75\x6d\x6d\x69' \
+ + b'\x74\x33\x30\x30\x2d\x34\x38\x20' \
+ + b'\x2d\x20\x56\x65\x72\x73\x69\x6f' \
+ + b'\x6e\x20\x37\x2e\x34\x65\x2e\x31' \
+ + b'\x20\x28\x42\x75\x69\x6c\x64\x20' \
+ + b'\x35\x29\x20\x62\x79\x20\x52\x65' \
+ + b'\x6c\x65\x61\x73\x65\x5f\x4d\x61' \
+ + b'\x73\x74\x65\x72\x20\x30\x35\x2f' \
+ + b'\x32\x37\x2f\x30\x35\x20\x30\x34' \
+ + b'\x3a\x35\x33\x3a\x31\x31\x00\x0e' \
+ + b'\x05\x01\x00\x14\x00\x14\x10\x0e' \
+ + b'\x07' \
+ + b'\x06\x00\x01\x30\xf9\xad\xa0\x02' \
+ + b'\x00\x00\x03\xe9\x00\xfe\x07\x00' \
+ + b'\x12\x0f\x02\x07\x01\x00\xfe\x09' \
+ + b'\x00\x12\x0f\x01\x03\x6c\x00\x00' \
+ + b'\x10\xfe\x09\x00\x12\x0f\x03\x01' \
+ + b'\x00\x00\x00\x00\xfe\x06\x00\x12' \
+ + b'\x0f\x04\x05\xf2\xfe\x06\x00\x80' \
+ + b'\xc2\x01\x01\xe8\xfe\x07\x00\x80' \
+ + b'\xc2\x02\x01\x00\x00\xfe\x17\x00' \
+ + b'\x80\xc2\x03\x01\xe8\x10\x76\x32' \
+ + b'\x2d\x30\x34\x38\x38\x2d\x30\x33' \
+ + b'\x2d\x30\x35\x30\x35\x00\xfe\x05' \
+ + b'\x00\x80\xc2\x04\x00\x00\x00'
+
+ def tearDown(self):
+ pass
+
+ def test_parse(self):
+ buf = self.data
+ pkt = packet.Packet(buf)
+ i = iter(pkt)
+
+ eq_(type(next(i)), ethernet.ethernet)
+ lldp_pkt = next(i)
+ eq_(type(lldp_pkt), lldp.lldp)
+
+ tlvs = lldp_pkt.tlvs
+
+ # Port Description
+ eq_(tlvs[3].tlv_type, lldp.LLDP_TLV_PORT_DESCRIPTION)
+ eq_(tlvs[3].port_description, b'Summit300-48-Port 1001\x00')
+
+ # System Name
+ eq_(tlvs[4].tlv_type, lldp.LLDP_TLV_SYSTEM_NAME)
+ eq_(tlvs[4].system_name, b'Summit300-48\x00')
+
+ # System Description
+
+ eq_(tlvs[5].tlv_type, lldp.LLDP_TLV_SYSTEM_DESCRIPTION)
+ eq_(tlvs[5].system_description,
+ b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ + b'by Release_Master 05/27/05 04:53:11\x00')
+
+ # SystemCapabilities
+ eq_(tlvs[6].tlv_type, lldp.LLDP_TLV_SYSTEM_CAPABILITIES)
+ eq_(tlvs[6].subtype, lldp.ChassisID.SUB_CHASSIS_COMPONENT)
+ eq_(tlvs[6].system_cap & lldp.SystemCapabilities.CAP_MAC_BRIDGE,
+ lldp.SystemCapabilities.CAP_MAC_BRIDGE)
+ eq_(tlvs[6].enabled_cap & lldp.SystemCapabilities.CAP_MAC_BRIDGE,
+ lldp.SystemCapabilities.CAP_MAC_BRIDGE)
+ eq_(tlvs[6].system_cap & lldp.SystemCapabilities.CAP_TELEPHONE, 0)
+ eq_(tlvs[6].enabled_cap & lldp.SystemCapabilities.CAP_TELEPHONE, 0)
+
+ # Management Address
+ eq_(tlvs[7].tlv_type, lldp.LLDP_TLV_MANAGEMENT_ADDRESS)
+ eq_(tlvs[7].addr_len, 7)
+ eq_(tlvs[7].addr, b'\x00\x01\x30\xf9\xad\xa0')
+ eq_(tlvs[7].intf_num, 1001)
+
+ # Organizationally Specific
+ eq_(tlvs[8].tlv_type, lldp.LLDP_TLV_ORGANIZATIONALLY_SPECIFIC)
+ eq_(tlvs[8].oui, b'\x00\x12\x0f') # IEEE 802.3
+ eq_(tlvs[8].subtype, 0x02) # Power Via MDI
+
+ # End
+ eq_(tlvs[16].tlv_type, lldp.LLDP_TLV_END)
+
+ def test_parse_corrupted(self):
+ buf = self.data
+ pkt = packet.Packet(buf[:128])
+
+ def test_serialize(self):
+ pkt = packet.Packet()
+
+ dst = lldp.LLDP_MAC_NEAREST_BRIDGE
+ src = '00:01:30:f9:ad:a0'
+ ethertype = ether.ETH_TYPE_LLDP
+ eth_pkt = ethernet.ethernet(dst, src, ethertype)
+ pkt.add_protocol(eth_pkt)
+
+ tlv_chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=addrconv.mac.
+ text_to_bin(src))
+ tlv_port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/1')
+ tlv_ttl = lldp.TTL(ttl=120)
+ tlv_port_description = lldp.PortDescription(
+ port_description=b'Summit300-48-Port 1001\x00')
+ tlv_system_name = lldp.SystemName(system_name=b'Summit300-48\x00')
+ tlv_system_description = lldp.SystemDescription(
+ system_description=b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ + b'by Release_Master 05/27/05 04:53:11\x00')
+ tlv_system_capabilities = lldp.SystemCapabilities(
+ subtype=lldp.ChassisID.SUB_CHASSIS_COMPONENT,
+ system_cap=0x14,
+ enabled_cap=0x14)
+ tlv_management_address = lldp.ManagementAddress(
+ addr_subtype=0x06, addr=b'\x00\x01\x30\xf9\xad\xa0',
+ intf_subtype=0x02, intf_num=1001,
+ oid=b'')
+ tlv_organizationally_specific = lldp.OrganizationallySpecific(
+ oui=b'\x00\x12\x0f', subtype=0x02, info=b'\x07\x01\x00')
+ tlv_end = lldp.End()
+ tlvs = (tlv_chassis_id, tlv_port_id, tlv_ttl, tlv_port_description,
+ tlv_system_name, tlv_system_description,
+ tlv_system_capabilities, tlv_management_address,
+ tlv_organizationally_specific, tlv_end)
+ lldp_pkt = lldp.lldp(tlvs)
+ pkt.add_protocol(lldp_pkt)
+
+ eq_(len(pkt.protocols), 2)
+
+ pkt.serialize()
+
+ # self.data has many organizationally specific TLVs
+ data = six.binary_type(pkt.data[:-2])
+ eq_(data, self.data[:len(data)])
+
+ def test_to_string(self):
+ chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=b'\x00\x01\x30\xf9\xad\xa0')
+ port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/1')
+ ttl = lldp.TTL(ttl=120)
+ port_desc = lldp.PortDescription(
+ port_description=b'Summit300-48-Port 1001\x00')
+ sys_name = lldp.SystemName(system_name=b'Summit300-48\x00')
+ sys_desc = lldp.SystemDescription(
+ system_description=b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ + b'by Release_Master 05/27/05 04:53:11\x00')
+ sys_cap = lldp.SystemCapabilities(
+ subtype=lldp.ChassisID.SUB_CHASSIS_COMPONENT,
+ system_cap=0x14,
+ enabled_cap=0x14)
+ man_addr = lldp.ManagementAddress(
+ addr_subtype=0x06, addr=b'\x00\x01\x30\xf9\xad\xa0',
+ intf_subtype=0x02, intf_num=1001,
+ oid='')
+ org_spec = lldp.OrganizationallySpecific(
+ oui=b'\x00\x12\x0f', subtype=0x02, info=b'\x07\x01\x00')
+ end = lldp.End()
+ tlvs = (chassis_id, port_id, ttl, port_desc, sys_name,
+ sys_desc, sys_cap, man_addr, org_spec, end)
+ lldp_pkt = lldp.lldp(tlvs)
+
+ # ChassisID string
+ chassis_id_values = {'subtype': lldp.ChassisID.SUB_MAC_ADDRESS,
+ 'chassis_id': b'\x00\x01\x30\xf9\xad\xa0',
+ 'len': chassis_id.len,
+ 'typelen': chassis_id.typelen}
+ _ch_id_str = ','.join(['%s=%s' % (k, repr(chassis_id_values[k]))
+ for k, v in inspect.getmembers(chassis_id)
+ if k in chassis_id_values])
+ tlv_chassis_id_str = '%s(%s)' % (lldp.ChassisID.__name__, _ch_id_str)
+
+ # PortID string
+ port_id_values = {'subtype': port_id.subtype,
+ 'port_id': port_id.port_id,
+ 'len': port_id.len,
+ 'typelen': port_id.typelen}
+ _port_id_str = ','.join(['%s=%s' % (k, repr(port_id_values[k]))
+ for k, v in inspect.getmembers(port_id)
+ if k in port_id_values])
+ tlv_port_id_str = '%s(%s)' % (lldp.PortID.__name__, _port_id_str)
+
+ # TTL string
+ ttl_values = {'ttl': ttl.ttl,
+ 'len': ttl.len,
+ 'typelen': ttl.typelen}
+ _ttl_str = ','.join(['%s=%s' % (k, repr(ttl_values[k]))
+ for k, v in inspect.getmembers(ttl)
+ if k in ttl_values])
+ tlv_ttl_str = '%s(%s)' % (lldp.TTL.__name__, _ttl_str)
+
+ # PortDescription string
+ port_desc_values = {'tlv_info': port_desc.tlv_info,
+ 'len': port_desc.len,
+ 'typelen': port_desc.typelen}
+ _port_desc_str = ','.join(['%s=%s' % (k, repr(port_desc_values[k]))
+ for k, v in inspect.getmembers(port_desc)
+ if k in port_desc_values])
+ tlv_port_desc_str = '%s(%s)' % (lldp.PortDescription.__name__,
+ _port_desc_str)
+
+ # SystemName string
+ sys_name_values = {'tlv_info': sys_name.tlv_info,
+ 'len': sys_name.len,
+ 'typelen': sys_name.typelen}
+ _system_name_str = ','.join(['%s=%s' % (k, repr(sys_name_values[k]))
+ for k, v in inspect.getmembers(sys_name)
+ if k in sys_name_values])
+ tlv_system_name_str = '%s(%s)' % (lldp.SystemName.__name__,
+ _system_name_str)
+
+ # SystemDescription string
+ sys_desc_values = {'tlv_info': sys_desc.tlv_info,
+ 'len': sys_desc.len,
+ 'typelen': sys_desc.typelen}
+ _sys_desc_str = ','.join(['%s=%s' % (k, repr(sys_desc_values[k]))
+ for k, v in inspect.getmembers(sys_desc)
+ if k in sys_desc_values])
+ tlv_sys_desc_str = '%s(%s)' % (lldp.SystemDescription.__name__,
+ _sys_desc_str)
+
+ # SystemCapabilities string
+ sys_cap_values = {'subtype': lldp.ChassisID.SUB_CHASSIS_COMPONENT,
+ 'system_cap': 0x14,
+ 'enabled_cap': 0x14,
+ 'len': sys_cap.len,
+ 'typelen': sys_cap.typelen}
+ _sys_cap_str = ','.join(['%s=%s' % (k, repr(sys_cap_values[k]))
+ for k, v in inspect.getmembers(sys_cap)
+ if k in sys_cap_values])
+ tlv_sys_cap_str = '%s(%s)' % (lldp.SystemCapabilities.__name__,
+ _sys_cap_str)
+
+ # ManagementAddress string
+ man_addr_values = {'addr_subtype': 0x06,
+ 'addr': b'\x00\x01\x30\xf9\xad\xa0',
+ 'addr_len': man_addr.addr_len,
+ 'intf_subtype': 0x02,
+ 'intf_num': 1001,
+ 'oid': '',
+ 'oid_len': man_addr.oid_len,
+ 'len': man_addr.len,
+ 'typelen': man_addr.typelen}
+ _man_addr_str = ','.join(['%s=%s' % (k, repr(man_addr_values[k]))
+ for k, v in inspect.getmembers(man_addr)
+ if k in man_addr_values])
+ tlv_man_addr_str = '%s(%s)' % (lldp.ManagementAddress.__name__,
+ _man_addr_str)
+
+ # OrganizationallySpecific string
+ org_spec_values = {'oui': b'\x00\x12\x0f',
+ 'subtype': 0x02,
+ 'info': b'\x07\x01\x00',
+ 'len': org_spec.len,
+ 'typelen': org_spec.typelen}
+ _org_spec_str = ','.join(['%s=%s' % (k, repr(org_spec_values[k]))
+ for k, v in inspect.getmembers(org_spec)
+ if k in org_spec_values])
+ tlv_org_spec_str = '%s(%s)' % (lldp.OrganizationallySpecific.__name__,
+ _org_spec_str)
+
+ # End string
+ end_values = {'len': end.len,
+ 'typelen': end.typelen}
+ _end_str = ','.join(['%s=%s' % (k, repr(end_values[k]))
+ for k, v in inspect.getmembers(end)
+ if k in end_values])
+ tlv_end_str = '%s(%s)' % (lldp.End.__name__, _end_str)
+
+ # tlvs string
+ _tlvs_str = '(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
+ tlvs_str = _tlvs_str % (tlv_chassis_id_str,
+ tlv_port_id_str,
+ tlv_ttl_str,
+ tlv_port_desc_str,
+ tlv_system_name_str,
+ tlv_sys_desc_str,
+ tlv_sys_cap_str,
+ tlv_man_addr_str,
+ tlv_org_spec_str,
+ tlv_end_str)
+
+ # lldp string
+ _lldp_str = '%s(tlvs=%s)'
+ lldp_str = _lldp_str % (lldp.lldp.__name__,
+ tlvs_str)
+
+ eq_(str(lldp_pkt), lldp_str)
+ eq_(repr(lldp_pkt), lldp_str)
+
+ def test_json(self):
+ chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_MAC_ADDRESS,
+ chassis_id=b'\x00\x01\x30\xf9\xad\xa0')
+ port_id = lldp.PortID(subtype=lldp.PortID.SUB_INTERFACE_NAME,
+ port_id=b'1/1')
+ ttl = lldp.TTL(ttl=120)
+ port_desc = lldp.PortDescription(
+ port_description=b'Summit300-48-Port 1001\x00')
+ sys_name = lldp.SystemName(system_name=b'Summit300-48\x00')
+ sys_desc = lldp.SystemDescription(
+ system_description=b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ + b'by Release_Master 05/27/05 04:53:11\x00')
+ sys_cap = lldp.SystemCapabilities(
+ subtype=lldp.ChassisID.SUB_CHASSIS_COMPONENT,
+ system_cap=0x14,
+ enabled_cap=0x14)
+ man_addr = lldp.ManagementAddress(
+ addr_subtype=0x06, addr=b'\x00\x01\x30\xf9\xad\xa0',
+ intf_subtype=0x02, intf_num=1001,
+ oid='')
+ org_spec = lldp.OrganizationallySpecific(
+ oui=b'\x00\x12\x0f', subtype=0x02, info=b'\x07\x01\x00')
+ end = lldp.End()
+ tlvs = (chassis_id, port_id, ttl, port_desc, sys_name,
+ sys_desc, sys_cap, man_addr, org_spec, end)
+ lldp1 = lldp.lldp(tlvs)
+ jsondict = lldp1.to_jsondict()
+ lldp2 = lldp.lldp.from_jsondict(jsondict['lldp'])
+ eq_(str(lldp1), str(lldp2))
diff --git a/tests/unit/packet/test_mpls.py b/tests/unit/packet/test_mpls.py
new file mode 100644
index 00000000..e3f9bccf
--- /dev/null
+++ b/tests/unit/packet/test_mpls.py
@@ -0,0 +1,92 @@
+# Copyright (C) 2013 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 unittest
+import logging
+import inspect
+
+from nose.tools import eq_
+from ryu.lib.packet import mpls
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_mpls(unittest.TestCase):
+
+ label = 29
+ exp = 6
+ bsb = 1
+ ttl = 64
+ mp = mpls.mpls(label, exp, bsb, ttl)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_to_string(self):
+ mpls_values = {'label': self.label,
+ 'exp': self.exp,
+ 'bsb': self.bsb,
+ 'ttl': self.ttl}
+ _mpls_str = ','.join(['%s=%s' % (k, repr(mpls_values[k]))
+ for k, v in inspect.getmembers(self.mp)
+ if k in mpls_values])
+ mpls_str = '%s(%s)' % (mpls.mpls.__name__, _mpls_str)
+
+ eq_(str(self.mp), mpls_str)
+ eq_(repr(self.mp), mpls_str)
+
+ def test_json(self):
+ jsondict = self.mp.to_jsondict()
+ mp = mpls.mpls.from_jsondict(jsondict['mpls'])
+ eq_(str(self.mp), str(mp))
+
+ def test_label_from_bin_true(self):
+ mpls_label = 0xfffff
+ is_bos = True
+ buf = b'\xff\xff\xf1'
+ mpls_label_out, is_bos_out = mpls.label_from_bin(buf)
+
+ eq_(mpls_label, mpls_label_out)
+ eq_(is_bos, is_bos_out)
+
+ def test_label_from_bin_false(self):
+ mpls_label = 0xfffff
+ is_bos = False
+ buf = b'\xff\xff\xf0'
+ mpls_label_out, is_bos_out = mpls.label_from_bin(buf)
+
+ eq_(mpls_label, mpls_label_out)
+ eq_(is_bos, is_bos_out)
+
+ def test_label_to_bin_true(self):
+ mpls_label = 0xfffff
+ is_bos = True
+ label = b'\xff\xff\xf1'
+ label_out = mpls.label_to_bin(mpls_label, is_bos)
+
+ eq_(label, label_out)
+
+ def test_label_to_bin_false(self):
+ mpls_label = 0xfffff
+ is_bos = False
+ label = b'\xff\xff\xf0'
+ label_out = mpls.label_to_bin(mpls_label, is_bos)
+
+ eq_(label, label_out)
diff --git a/tests/unit/packet/test_openflow.py b/tests/unit/packet/test_openflow.py
new file mode 100644
index 00000000..b0dca25f
--- /dev/null
+++ b/tests/unit/packet/test_openflow.py
@@ -0,0 +1,64 @@
+# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+
+import logging
+import os
+import sys
+
+import unittest
+from nose.tools import eq_
+from nose.tools import ok_
+
+from ryu.lib import pcaplib
+from ryu.lib.packet import openflow
+from ryu.lib.packet import packet
+from ryu.utils import binary_str
+
+
+LOG = logging.getLogger(__name__)
+
+OPENFLOW_DATA_DIR = os.path.join(
+ os.path.dirname(sys.modules[__name__].__file__),
+ '../../packet_data/pcap/')
+
+
+class Test_openflow(unittest.TestCase):
+ """
+ Test case for ryu.lib.packet.openflow.
+ """
+
+ def test_pcap(self):
+ files = [
+ 'openflow_flowmod',
+ 'openflow_flowstats_req',
+ 'openflow_invalid_version',
+ ]
+
+ for f in files:
+ # print('*** testing %s ...' % f)
+ for _, buf in pcaplib.Reader(
+ open(OPENFLOW_DATA_DIR + f + '.pcap', 'rb')):
+ # Checks if message can be parsed as expected.
+ pkt = packet.Packet(buf)
+ openflow_pkt = pkt.get_protocol(openflow.openflow)
+ ok_(isinstance(openflow_pkt, openflow.openflow),
+ 'Failed to parse OpenFlow message: %s' % pkt)
+
+ # Checks if message can be serialized as expected.
+ pkt.serialize()
+ eq_(buf, pkt.data,
+ "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))
diff --git a/tests/unit/packet/test_ospf.py b/tests/unit/packet/test_ospf.py
new file mode 100644
index 00000000..df57b8de
--- /dev/null
+++ b/tests/unit/packet/test_ospf.py
@@ -0,0 +1,120 @@
+# Copyright (C) 2013 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 unittest
+from nose.tools import eq_
+from nose.tools import ok_
+
+from ryu.lib.packet import ospf
+
+
+class Test_ospf(unittest.TestCase):
+ """ Test case for ryu.lib.packet.ospf
+ """
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_router_lsa(self):
+ link1 = ospf.RouterLSA.Link(id_='10.0.0.1', data='255.255.255.0',
+ type_=ospf.LSA_LINK_TYPE_STUB, metric=10)
+ msg = ospf.RouterLSA(id_='192.168.0.1', adv_router='192.168.0.2',
+ links=[link1])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.LSA.parser(binmsg)
+ eq_(msg.header.checksum, msg2.header.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_network_lsa(self):
+ msg = ospf.NetworkLSA(id_='192.168.0.1', adv_router='192.168.0.2',
+ mask='255.255.255.0', routers=['192.168.0.2'])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.LSA.parser(binmsg)
+ eq_(msg.header.checksum, msg2.header.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_as_external_lsa(self):
+ extnw1 = ospf.ASExternalLSA.ExternalNetwork(mask='255.255.255.0',
+ metric=20,
+ fwd_addr='10.0.0.1')
+ msg = ospf.ASExternalLSA(id_='192.168.0.1', adv_router='192.168.0.2',
+ extnws=[extnw1])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.LSA.parser(binmsg)
+ eq_(msg.header.checksum, msg2.header.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_hello(self):
+ msg = ospf.OSPFHello(router_id='192.168.0.1',
+ neighbors=['192.168.0.2'])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.OSPFMessage.parser(binmsg)
+ eq_(msg.checksum, msg2.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_dbdesc(self):
+ link1 = ospf.RouterLSA.Link(id_='10.0.0.1', data='255.255.255.0',
+ type_=ospf.LSA_LINK_TYPE_STUB, metric=10)
+ lsa1 = ospf.RouterLSA(id_='192.168.0.1', adv_router='192.168.0.2',
+ links=[link1])
+ msg = ospf.OSPFDBDesc(router_id='192.168.0.1',
+ lsa_headers=[lsa1.header])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.OSPFMessage.parser(binmsg)
+ eq_(msg.checksum, msg2.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_lsreq(self):
+ req = ospf.OSPFLSReq.Request(type_=ospf.OSPF_ROUTER_LSA,
+ id_='192.168.0.1',
+ adv_router='192.168.0.2')
+ msg = ospf.OSPFLSReq(router_id='192.168.0.1', lsa_requests=[req])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.OSPFMessage.parser(binmsg)
+ eq_(msg.checksum, msg2.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_lsupd(self):
+ link1 = ospf.RouterLSA.Link(id_='10.0.0.1', data='255.255.255.0',
+ type_=ospf.LSA_LINK_TYPE_STUB, metric=10)
+ lsa1 = ospf.RouterLSA(id_='192.168.0.1', adv_router='192.168.0.2',
+ links=[link1])
+ msg = ospf.OSPFLSUpd(router_id='192.168.0.1', lsas=[lsa1])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.OSPFMessage.parser(binmsg)
+ eq_(msg.checksum, msg2.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
+
+ def test_lsack(self):
+ link1 = ospf.RouterLSA.Link(id_='10.0.0.1', data='255.255.255.0',
+ type_=ospf.LSA_LINK_TYPE_STUB, metric=10)
+ lsa1 = ospf.RouterLSA(id_='192.168.0.1', adv_router='192.168.0.2',
+ links=[link1])
+ msg = ospf.OSPFLSAck(router_id='192.168.0.1',
+ lsa_headers=[lsa1.header])
+ binmsg = msg.serialize()
+ msg2, cls, rest = ospf.OSPFMessage.parser(binmsg)
+ eq_(msg.checksum, msg2.checksum)
+ eq_(str(msg), str(msg2))
+ eq_(rest, b'')
diff --git a/tests/unit/packet/test_packet.py b/tests/unit/packet/test_packet.py
new file mode 100644
index 00000000..1b4c704b
--- /dev/null
+++ b/tests/unit/packet/test_packet.py
@@ -0,0 +1,1553 @@
+# 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 unittest
+import logging
+import struct
+import inspect
+from nose.tools import ok_, eq_
+import six
+from ryu.ofproto import ether, inet
+from ryu.lib.packet import arp
+from ryu.lib.packet import bpdu
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import icmp, icmpv6
+from ryu.lib.packet import ipv4, ipv6
+from ryu.lib.packet import llc
+from ryu.lib.packet import packet, packet_utils
+from ryu.lib.packet import sctp
+from ryu.lib.packet import tcp, udp
+from ryu.lib.packet import vlan
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger('test_packet')
+
+
+class TestPacket(unittest.TestCase):
+ """ Test case for packet
+ """
+
+ dst_mac = 'aa:aa:aa:aa:aa:aa'
+ src_mac = 'bb:bb:bb:bb:bb:bb'
+ dst_mac_bin = addrconv.mac.text_to_bin(dst_mac)
+ src_mac_bin = addrconv.mac.text_to_bin(src_mac)
+ dst_ip = '192.168.128.10'
+ src_ip = '192.168.122.20'
+ dst_ip_bin = addrconv.ipv4.text_to_bin(dst_ip)
+ src_port = 50001
+ dst_port = 50002
+ src_ip_bin = addrconv.ipv4.text_to_bin(src_ip)
+ payload = b'\x06\x06\x47\x50\x00\x00\x00\x00' \
+ + b'\xcd\xc5\x00\x00\x00\x00\x00\x00' \
+ + b'\x10\x11\x12\x13\x14\x15\x16\x17' \
+ + b'\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'
+
+ 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 setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_arp(self):
+ # buid packet
+ e = ethernet.ethernet(self.dst_mac, self.src_mac,
+ ether.ETH_TYPE_ARP)
+ a = arp.arp(1, ether.ETH_TYPE_IP, 6, 4, 2,
+ self.src_mac, self.src_ip, self.dst_mac,
+ self.dst_ip)
+ p = packet.Packet()
+ p.add_protocol(e)
+ p.add_protocol(a)
+ p.serialize()
+
+ # ethernet !6s6sH
+ e_buf = self.dst_mac_bin \
+ + self.src_mac_bin \
+ + b'\x08\x06'
+
+ # arp !HHBBH6sI6sI
+ a_buf = b'\x00\x01' \
+ + b'\x08\x00' \
+ + b'\x06' \
+ + b'\x04' \
+ + b'\x00\x02' \
+ + self.src_mac_bin \
+ + self.src_ip_bin \
+ + self.dst_mac_bin \
+ + self.dst_ip_bin
+
+ buf = e_buf + a_buf
+
+ # Append padding if ethernet frame is less than 60 bytes length
+ pad_len = 60 - len(buf)
+ if pad_len > 0:
+ buf += b'\x00' * pad_len
+ eq_(buf, p.data)
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_arp = protocols['arp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_(self.dst_mac, p_eth.dst)
+ eq_(self.src_mac, p_eth.src)
+ eq_(ether.ETH_TYPE_ARP, p_eth.ethertype)
+
+ # arp
+ ok_(p_arp)
+ eq_(1, p_arp.hwtype)
+ eq_(ether.ETH_TYPE_IP, p_arp.proto)
+ eq_(6, p_arp.hlen)
+ eq_(4, p_arp.plen)
+ eq_(2, p_arp.opcode)
+ eq_(self.src_mac, p_arp.src_mac)
+ eq_(self.src_ip, p_arp.src_ip)
+ eq_(self.dst_mac, p_arp.dst_mac)
+ eq_(self.dst_ip, p_arp.dst_ip)
+
+ # to string
+ eth_values = {'dst': self.dst_mac,
+ 'src': self.src_mac,
+ 'ethertype': ether.ETH_TYPE_ARP}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ arp_values = {'hwtype': 1,
+ 'proto': ether.ETH_TYPE_IP,
+ 'hlen': 6,
+ 'plen': 4,
+ 'opcode': 2,
+ 'src_mac': self.src_mac,
+ 'dst_mac': self.dst_mac,
+ 'src_ip': self.src_ip,
+ 'dst_ip': self.dst_ip}
+ _arp_str = ','.join(['%s=%s' % (k, repr(arp_values[k]))
+ for k, v in inspect.getmembers(p_arp)
+ if k in arp_values])
+ arp_str = '%s(%s)' % (arp.arp.__name__, _arp_str)
+
+ pkt_str = '%s, %s' % (eth_str, arp_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(arp_str, str(p_arp))
+ eq_(arp_str, repr(p_arp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_vlan_arp(self):
+ # buid packet
+ e = ethernet.ethernet(self.dst_mac, self.src_mac,
+ ether.ETH_TYPE_8021Q)
+ v = vlan.vlan(0b111, 0b1, 3, ether.ETH_TYPE_ARP)
+ a = arp.arp(1, ether.ETH_TYPE_IP, 6, 4, 2,
+ self.src_mac, self.src_ip, self.dst_mac,
+ self.dst_ip)
+ p = packet.Packet()
+ p.add_protocol(e)
+ p.add_protocol(v)
+ p.add_protocol(a)
+ p.serialize()
+
+ # ethernet !6s6sH
+ e_buf = self.dst_mac_bin \
+ + self.src_mac_bin \
+ + b'\x81\x00'
+
+ # vlan !HH
+ v_buf = b'\xF0\x03' \
+ + b'\x08\x06'
+
+ # arp !HHBBH6sI6sI
+ a_buf = b'\x00\x01' \
+ + b'\x08\x00' \
+ + b'\x06' \
+ + b'\x04' \
+ + b'\x00\x02' \
+ + self.src_mac_bin \
+ + self.src_ip_bin \
+ + self.dst_mac_bin \
+ + self.dst_ip_bin
+
+ buf = e_buf + v_buf + a_buf
+
+ # Append padding if ethernet frame is less than 60 bytes length
+ pad_len = 60 - len(buf)
+ if pad_len > 0:
+ buf += b'\x00' * pad_len
+ eq_(buf, p.data)
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_vlan = protocols['vlan']
+ p_arp = protocols['arp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_(self.dst_mac, p_eth.dst)
+ eq_(self.src_mac, p_eth.src)
+ eq_(ether.ETH_TYPE_8021Q, p_eth.ethertype)
+
+ # vlan
+ ok_(p_vlan)
+ eq_(0b111, p_vlan.pcp)
+ eq_(0b1, p_vlan.cfi)
+ eq_(3, p_vlan.vid)
+ eq_(ether.ETH_TYPE_ARP, p_vlan.ethertype)
+
+ # arp
+ ok_(p_arp)
+ eq_(1, p_arp.hwtype)
+ eq_(ether.ETH_TYPE_IP, p_arp.proto)
+ eq_(6, p_arp.hlen)
+ eq_(4, p_arp.plen)
+ eq_(2, p_arp.opcode)
+ eq_(self.src_mac, p_arp.src_mac)
+ eq_(self.src_ip, p_arp.src_ip)
+ eq_(self.dst_mac, p_arp.dst_mac)
+ eq_(self.dst_ip, p_arp.dst_ip)
+
+ # to string
+ eth_values = {'dst': self.dst_mac,
+ 'src': self.src_mac,
+ 'ethertype': ether.ETH_TYPE_8021Q}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ vlan_values = {'pcp': 0b111,
+ 'cfi': 0b1,
+ 'vid': 3,
+ 'ethertype': ether.ETH_TYPE_ARP}
+ _vlan_str = ','.join(['%s=%s' % (k, repr(vlan_values[k]))
+ for k, v in inspect.getmembers(p_vlan)
+ if k in vlan_values])
+ vlan_str = '%s(%s)' % (vlan.vlan.__name__, _vlan_str)
+
+ arp_values = {'hwtype': 1,
+ 'proto': ether.ETH_TYPE_IP,
+ 'hlen': 6,
+ 'plen': 4,
+ 'opcode': 2,
+ 'src_mac': self.src_mac,
+ 'dst_mac': self.dst_mac,
+ 'src_ip': self.src_ip,
+ 'dst_ip': self.dst_ip}
+ _arp_str = ','.join(['%s=%s' % (k, repr(arp_values[k]))
+ for k, v in inspect.getmembers(p_arp)
+ if k in arp_values])
+ arp_str = '%s(%s)' % (arp.arp.__name__, _arp_str)
+
+ pkt_str = '%s, %s, %s' % (eth_str, vlan_str, arp_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(vlan_str, str(p_vlan))
+ eq_(vlan_str, repr(p_vlan))
+
+ eq_(arp_str, str(p_arp))
+ eq_(arp_str, repr(p_arp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv4_udp(self):
+ # buid packet
+ e = ethernet.ethernet(self.dst_mac, self.src_mac,
+ ether.ETH_TYPE_IP)
+ ip = ipv4.ipv4(4, 5, 1, 0, 3, 1, 4, 64, inet.IPPROTO_UDP, 0,
+ self.src_ip, self.dst_ip)
+ u = udp.udp(0x190F, 0x1F90, 0, 0)
+
+ p = packet.Packet()
+ p.add_protocol(e)
+ p.add_protocol(ip)
+ p.add_protocol(u)
+ p.add_protocol(self.payload)
+ p.serialize()
+
+ # ethernet !6s6sH
+ e_buf = self.dst_mac_bin \
+ + self.src_mac_bin \
+ + b'\x08\x00'
+
+ # ipv4 !BBHHHBBHII
+ ip_buf = b'\x45' \
+ + b'\x01' \
+ + b'\x00\x3C' \
+ + b'\x00\x03' \
+ + b'\x20\x04' \
+ + b'\x40' \
+ + b'\x11' \
+ + b'\x00\x00' \
+ + self.src_ip_bin \
+ + self.dst_ip_bin
+
+ # udp !HHHH
+ u_buf = b'\x19\x0F' \
+ + b'\x1F\x90' \
+ + b'\x00\x28' \
+ + b'\x00\x00'
+
+ buf = e_buf + ip_buf + u_buf + self.payload
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv4 = protocols['ipv4']
+ p_udp = protocols['udp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_(self.dst_mac, p_eth.dst)
+ eq_(self.src_mac, p_eth.src)
+ eq_(ether.ETH_TYPE_IP, p_eth.ethertype)
+
+ # ipv4
+ ok_(p_ipv4)
+ eq_(4, p_ipv4.version)
+ eq_(5, p_ipv4.header_length)
+ eq_(1, p_ipv4.tos)
+ l = len(ip_buf) + len(u_buf) + len(self.payload)
+ eq_(l, p_ipv4.total_length)
+ eq_(3, p_ipv4.identification)
+ eq_(1, p_ipv4.flags)
+ eq_(64, p_ipv4.ttl)
+ eq_(inet.IPPROTO_UDP, p_ipv4.proto)
+ eq_(self.src_ip, p_ipv4.src)
+ eq_(self.dst_ip, p_ipv4.dst)
+ t = bytearray(ip_buf)
+ struct.pack_into('!H', t, 10, p_ipv4.csum)
+ eq_(packet_utils.checksum(t), 0)
+
+ # udp
+ ok_(p_udp)
+ eq_(0x190f, p_udp.src_port)
+ eq_(0x1F90, p_udp.dst_port)
+ eq_(len(u_buf) + len(self.payload), p_udp.total_length)
+ eq_(0x77b2, p_udp.csum)
+ t = bytearray(u_buf)
+ struct.pack_into('!H', t, 6, p_udp.csum)
+ ph = struct.pack('!4s4sBBH', self.src_ip_bin, self.dst_ip_bin, 0,
+ 17, len(u_buf) + len(self.payload))
+ t = ph + t + self.payload
+ eq_(packet_utils.checksum(t), 0)
+
+ # payload
+ ok_('payload' in protocols)
+ eq_(self.payload, protocols['payload'])
+
+ # to string
+ eth_values = {'dst': self.dst_mac,
+ 'src': self.src_mac,
+ 'ethertype': ether.ETH_TYPE_IP}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv4_values = {'version': 4,
+ 'header_length': 5,
+ 'tos': 1,
+ 'total_length': l,
+ 'identification': 3,
+ 'flags': 1,
+ 'offset': p_ipv4.offset,
+ 'ttl': 64,
+ 'proto': inet.IPPROTO_UDP,
+ 'csum': p_ipv4.csum,
+ 'src': self.src_ip,
+ 'dst': self.dst_ip,
+ 'option': None}
+ _ipv4_str = ','.join(['%s=%s' % (k, repr(ipv4_values[k]))
+ for k, v in inspect.getmembers(p_ipv4)
+ if k in ipv4_values])
+ ipv4_str = '%s(%s)' % (ipv4.ipv4.__name__, _ipv4_str)
+
+ udp_values = {'src_port': 0x190f,
+ 'dst_port': 0x1F90,
+ 'total_length': len(u_buf) + len(self.payload),
+ 'csum': 0x77b2}
+ _udp_str = ','.join(['%s=%s' % (k, repr(udp_values[k]))
+ for k, v in inspect.getmembers(p_udp)
+ if k in udp_values])
+ udp_str = '%s(%s)' % (udp.udp.__name__, _udp_str)
+
+ pkt_str = '%s, %s, %s, %s' % (eth_str, ipv4_str, udp_str,
+ repr(protocols['payload']))
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv4_str, str(p_ipv4))
+ eq_(ipv4_str, repr(p_ipv4))
+
+ eq_(udp_str, str(p_udp))
+ eq_(udp_str, repr(p_udp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv4_tcp(self):
+ # buid packet
+ e = ethernet.ethernet(self.dst_mac, self.src_mac,
+ ether.ETH_TYPE_IP)
+ ip = ipv4.ipv4(4, 5, 0, 0, 0, 0, 0, 64, inet.IPPROTO_TCP, 0,
+ self.src_ip, self.dst_ip)
+ t = tcp.tcp(0x190F, 0x1F90, 0x123, 1, 6, 0b101010, 2048, 0, 0x6f,
+ b'\x01\x02')
+
+ p = packet.Packet()
+ p.add_protocol(e)
+ p.add_protocol(ip)
+ p.add_protocol(t)
+ p.add_protocol(self.payload)
+ p.serialize()
+
+ # ethernet !6s6sH
+ e_buf = self.dst_mac_bin \
+ + self.src_mac_bin \
+ + b'\x08\x00'
+
+ # ipv4 !BBHHHBBHII
+ ip_buf = b'\x45' \
+ + b'\x00' \
+ + b'\x00\x4C' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x40' \
+ + b'\x06' \
+ + b'\x00\x00' \
+ + self.src_ip_bin \
+ + self.dst_ip_bin
+
+ # tcp !HHIIBBHHH + option
+ t_buf = b'\x19\x0F' \
+ + b'\x1F\x90' \
+ + b'\x00\x00\x01\x23' \
+ + b'\x00\x00\x00\x01' \
+ + b'\x60' \
+ + b'\x2A' \
+ + b'\x08\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x6F' \
+ + b'\x01\x02\x00\x00'
+
+ buf = e_buf + ip_buf + t_buf + self.payload
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv4 = protocols['ipv4']
+ p_tcp = protocols['tcp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_(self.dst_mac, p_eth.dst)
+ eq_(self.src_mac, p_eth.src)
+ eq_(ether.ETH_TYPE_IP, p_eth.ethertype)
+
+ # ipv4
+ ok_(p_ipv4)
+ eq_(4, p_ipv4.version)
+ eq_(5, p_ipv4.header_length)
+ eq_(0, p_ipv4.tos)
+ l = len(ip_buf) + len(t_buf) + len(self.payload)
+ eq_(l, p_ipv4.total_length)
+ eq_(0, p_ipv4.identification)
+ eq_(0, p_ipv4.flags)
+ eq_(64, p_ipv4.ttl)
+ eq_(inet.IPPROTO_TCP, p_ipv4.proto)
+ eq_(self.src_ip, p_ipv4.src)
+ eq_(self.dst_ip, p_ipv4.dst)
+ t = bytearray(ip_buf)
+ struct.pack_into('!H', t, 10, p_ipv4.csum)
+ eq_(packet_utils.checksum(t), 0)
+
+ # tcp
+ ok_(p_tcp)
+ eq_(0x190f, p_tcp.src_port)
+ eq_(0x1F90, p_tcp.dst_port)
+ eq_(0x123, p_tcp.seq)
+ eq_(1, p_tcp.ack)
+ eq_(6, p_tcp.offset)
+ eq_(0b101010, p_tcp.bits)
+ eq_(2048, p_tcp.window_size)
+ eq_(0x6f, p_tcp.urgent)
+ eq_(len(t_buf), len(p_tcp))
+ t = bytearray(t_buf)
+ struct.pack_into('!H', t, 16, p_tcp.csum)
+ ph = struct.pack('!4s4sBBH', self.src_ip_bin, self.dst_ip_bin, 0,
+ 6, len(t_buf) + len(self.payload))
+ t = ph + t + self.payload
+ eq_(packet_utils.checksum(t), 0)
+
+ # payload
+ ok_('payload' in protocols)
+ eq_(self.payload, protocols['payload'])
+
+ # to string
+ eth_values = {'dst': self.dst_mac,
+ 'src': self.src_mac,
+ 'ethertype': ether.ETH_TYPE_IP}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv4_values = {'version': 4,
+ 'header_length': 5,
+ 'tos': 0,
+ 'total_length': l,
+ 'identification': 0,
+ 'flags': 0,
+ 'offset': p_ipv4.offset,
+ 'ttl': 64,
+ 'proto': inet.IPPROTO_TCP,
+ 'csum': p_ipv4.csum,
+ 'src': self.src_ip,
+ 'dst': self.dst_ip,
+ 'option': None}
+ _ipv4_str = ','.join(['%s=%s' % (k, repr(ipv4_values[k]))
+ for k, v in inspect.getmembers(p_ipv4)
+ if k in ipv4_values])
+ ipv4_str = '%s(%s)' % (ipv4.ipv4.__name__, _ipv4_str)
+
+ tcp_values = {'src_port': 0x190f,
+ 'dst_port': 0x1F90,
+ 'seq': 0x123,
+ 'ack': 1,
+ 'offset': 6,
+ 'bits': 0b101010,
+ 'window_size': 2048,
+ 'csum': p_tcp.csum,
+ 'urgent': 0x6f,
+ 'option': p_tcp.option}
+ _tcp_str = ','.join(['%s=%s' % (k, repr(tcp_values[k]))
+ for k, v in inspect.getmembers(p_tcp)
+ if k in tcp_values])
+ tcp_str = '%s(%s)' % (tcp.tcp.__name__, _tcp_str)
+
+ pkt_str = '%s, %s, %s, %s' % (eth_str, ipv4_str, tcp_str,
+ repr(protocols['payload']))
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv4_str, str(p_ipv4))
+ eq_(ipv4_str, repr(p_ipv4))
+
+ eq_(tcp_str, str(p_tcp))
+ eq_(tcp_str, repr(p_tcp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv4_sctp(self):
+ # build packet
+ e = ethernet.ethernet()
+ ip = ipv4.ipv4(proto=inet.IPPROTO_SCTP)
+ s = sctp.sctp(chunks=[sctp.chunk_data(payload_data=self.payload)])
+
+ p = e / ip / s
+ p.serialize()
+
+ ipaddr = addrconv.ipv4.text_to_bin('0.0.0.0')
+
+ # ethernet !6s6sH
+ e_buf = b'\xff\xff\xff\xff\xff\xff' \
+ + b'\x00\x00\x00\x00\x00\x00' \
+ + b'\x08\x00'
+
+ # ipv4 !BBHHHBBHII
+ ip_buf = b'\x45' \
+ + b'\x00' \
+ + b'\x00\x50' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\xff' \
+ + b'\x84' \
+ + b'\x00\x00' \
+ + ipaddr \
+ + ipaddr
+
+ # sctp !HHII + chunk_data !BBHIHHI + payload
+ s_buf = b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00' \
+ + b'\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + self.payload
+
+ buf = e_buf + ip_buf + s_buf
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv4 = protocols['ipv4']
+ p_sctp = protocols['sctp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_('ff:ff:ff:ff:ff:ff', p_eth.dst)
+ eq_('00:00:00:00:00:00', p_eth.src)
+ eq_(ether.ETH_TYPE_IP, p_eth.ethertype)
+
+ # ipv4
+ ok_(p_ipv4)
+ eq_(4, p_ipv4.version)
+ eq_(5, p_ipv4.header_length)
+ eq_(0, p_ipv4.tos)
+ l = len(ip_buf) + len(s_buf)
+ eq_(l, p_ipv4.total_length)
+ eq_(0, p_ipv4.identification)
+ eq_(0, p_ipv4.flags)
+ eq_(255, p_ipv4.ttl)
+ eq_(inet.IPPROTO_SCTP, p_ipv4.proto)
+ eq_('10.0.0.1', p_ipv4.src)
+ eq_('10.0.0.2', p_ipv4.dst)
+ t = bytearray(ip_buf)
+ struct.pack_into('!H', t, 10, p_ipv4.csum)
+ eq_(packet_utils.checksum(t), 0x1403)
+
+ # sctp
+ ok_(p_sctp)
+ eq_(1, p_sctp.src_port)
+ eq_(1, p_sctp.dst_port)
+ eq_(0, p_sctp.vtag)
+ assert isinstance(p_sctp.chunks[0], sctp.chunk_data)
+ eq_(0, p_sctp.chunks[0]._type)
+ eq_(0, p_sctp.chunks[0].unordered)
+ eq_(0, p_sctp.chunks[0].begin)
+ eq_(0, p_sctp.chunks[0].end)
+ eq_(16 + len(self.payload), p_sctp.chunks[0].length)
+ eq_(0, p_sctp.chunks[0].tsn)
+ eq_(0, p_sctp.chunks[0].sid)
+ eq_(0, p_sctp.chunks[0].seq)
+ eq_(0, p_sctp.chunks[0].payload_id)
+ eq_(self.payload, p_sctp.chunks[0].payload_data)
+ eq_(len(s_buf), len(p_sctp))
+
+ # to string
+ eth_values = {'dst': 'ff:ff:ff:ff:ff:ff',
+ 'src': '00:00:00:00:00:00',
+ 'ethertype': ether.ETH_TYPE_IP}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv4_values = {'version': 4,
+ 'header_length': 5,
+ 'tos': 0,
+ 'total_length': l,
+ 'identification': 0,
+ 'flags': 0,
+ 'offset': 0,
+ 'ttl': 255,
+ 'proto': inet.IPPROTO_SCTP,
+ 'csum': p_ipv4.csum,
+ 'src': '10.0.0.1',
+ 'dst': '10.0.0.2',
+ 'option': None}
+ _ipv4_str = ','.join(['%s=%s' % (k, repr(ipv4_values[k]))
+ for k, v in inspect.getmembers(p_ipv4)
+ if k in ipv4_values])
+ ipv4_str = '%s(%s)' % (ipv4.ipv4.__name__, _ipv4_str)
+
+ data_values = {'unordered': 0,
+ 'begin': 0,
+ 'end': 0,
+ 'length': 16 + len(self.payload),
+ 'tsn': 0,
+ 'sid': 0,
+ 'seq': 0,
+ 'payload_id': 0,
+ 'payload_data': self.payload}
+ _data_str = ','.join(['%s=%s' % (k, repr(data_values[k]))
+ for k in sorted(data_values.keys())])
+ data_str = '[%s(%s)]' % (sctp.chunk_data.__name__, _data_str)
+
+ sctp_values = {'src_port': 1,
+ 'dst_port': 1,
+ 'vtag': 0,
+ 'csum': repr(p_sctp.csum),
+ 'chunks': data_str}
+ _sctp_str = ','.join(['%s=%s' % (k, sctp_values[k])
+ for k, _ in inspect.getmembers(p_sctp)
+ if k in sctp_values])
+ sctp_str = '%s(%s)' % (sctp.sctp.__name__, _sctp_str)
+
+ pkt_str = '%s, %s, %s' % (eth_str, ipv4_str, sctp_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv4_str, str(p_ipv4))
+ eq_(ipv4_str, repr(p_ipv4))
+
+ eq_(sctp_str, str(p_sctp))
+ eq_(sctp_str, repr(p_sctp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv4_icmp(self):
+ # buid packet
+ e = ethernet.ethernet()
+ ip = ipv4.ipv4(proto=inet.IPPROTO_ICMP)
+ ic = icmp.icmp()
+
+ p = e / ip / ic
+ p.serialize()
+
+ ipaddr = addrconv.ipv4.text_to_bin('0.0.0.0')
+
+ # ethernet !6s6sH
+ e_buf = b'\xff\xff\xff\xff\xff\xff' \
+ + b'\x00\x00\x00\x00\x00\x00' \
+ + b'\x08\x00'
+
+ # ipv4 !BBHHHBBHII
+ ip_buf = b'\x45' \
+ + b'\x00' \
+ + b'\x00\x1c' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\xff' \
+ + b'\x01' \
+ + b'\x00\x00' \
+ + ipaddr \
+ + ipaddr
+
+ # icmp !BBH + echo !HH
+ ic_buf = b'\x08' \
+ + b'\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00'
+
+ buf = e_buf + ip_buf + ic_buf
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv4 = protocols['ipv4']
+ p_icmp = protocols['icmp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_('ff:ff:ff:ff:ff:ff', p_eth.dst)
+ eq_('00:00:00:00:00:00', p_eth.src)
+ eq_(ether.ETH_TYPE_IP, p_eth.ethertype)
+
+ # ipv4
+ ok_(p_ipv4)
+ eq_(4, p_ipv4.version)
+ eq_(5, p_ipv4.header_length)
+ eq_(0, p_ipv4.tos)
+ l = len(ip_buf) + len(ic_buf)
+ eq_(l, p_ipv4.total_length)
+ eq_(0, p_ipv4.identification)
+ eq_(0, p_ipv4.flags)
+ eq_(255, p_ipv4.ttl)
+ eq_(inet.IPPROTO_ICMP, p_ipv4.proto)
+ eq_('10.0.0.1', p_ipv4.src)
+ eq_('10.0.0.2', p_ipv4.dst)
+ t = bytearray(ip_buf)
+ struct.pack_into('!H', t, 10, p_ipv4.csum)
+ eq_(packet_utils.checksum(t), 0x1403)
+
+ # icmp
+ ok_(p_icmp)
+ eq_(8, p_icmp.type)
+ eq_(0, p_icmp.code)
+ eq_(0, p_icmp.data.id)
+ eq_(0, p_icmp.data.seq)
+ eq_(len(ic_buf), len(p_icmp))
+ t = bytearray(ic_buf)
+ struct.pack_into('!H', t, 2, p_icmp.csum)
+ eq_(packet_utils.checksum(t), 0)
+
+ # to string
+ eth_values = {'dst': 'ff:ff:ff:ff:ff:ff',
+ 'src': '00:00:00:00:00:00',
+ 'ethertype': ether.ETH_TYPE_IP}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, _ in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv4_values = {'version': 4,
+ 'header_length': 5,
+ 'tos': 0,
+ 'total_length': l,
+ 'identification': 0,
+ 'flags': 0,
+ 'offset': p_ipv4.offset,
+ 'ttl': 255,
+ 'proto': inet.IPPROTO_ICMP,
+ 'csum': p_ipv4.csum,
+ 'src': '10.0.0.1',
+ 'dst': '10.0.0.2',
+ 'option': None}
+ _ipv4_str = ','.join(['%s=%s' % (k, repr(ipv4_values[k]))
+ for k, _ in inspect.getmembers(p_ipv4)
+ if k in ipv4_values])
+ ipv4_str = '%s(%s)' % (ipv4.ipv4.__name__, _ipv4_str)
+
+ echo_values = {'id': 0,
+ 'seq': 0,
+ 'data': None}
+ _echo_str = ','.join(['%s=%s' % (k, repr(echo_values[k]))
+ for k in sorted(echo_values.keys())])
+ echo_str = '%s(%s)' % (icmp.echo.__name__, _echo_str)
+ icmp_values = {'type': 8,
+ 'code': 0,
+ 'csum': p_icmp.csum,
+ 'data': echo_str}
+ _icmp_str = ','.join(['%s=%s' % (k, icmp_values[k])
+ for k, _ in inspect.getmembers(p_icmp)
+ if k in icmp_values])
+ icmp_str = '%s(%s)' % (icmp.icmp.__name__, _icmp_str)
+
+ pkt_str = '%s, %s, %s' % (eth_str, ipv4_str, icmp_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv4_str, str(p_ipv4))
+ eq_(ipv4_str, repr(p_ipv4))
+
+ eq_(icmp_str, str(p_icmp))
+ eq_(icmp_str, repr(p_icmp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv6_udp(self):
+ # build packet
+ e = ethernet.ethernet(ethertype=ether.ETH_TYPE_IPV6)
+ ip = ipv6.ipv6(nxt=inet.IPPROTO_UDP)
+ u = udp.udp()
+
+ p = e / ip / u / self.payload
+ p.serialize()
+
+ ipaddr = addrconv.ipv6.text_to_bin('::')
+
+ # ethernet !6s6sH
+ e_buf = b'\xff\xff\xff\xff\xff\xff' \
+ + b'\x00\x00\x00\x00\x00\x00' \
+ + b'\x86\xdd'
+
+ # ipv6 !IHBB16s16s'
+ ip_buf = b'\x60\x00\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x11' \
+ + b'\xff' \
+ + b'\x00\x00' \
+ + ipaddr \
+ + ipaddr
+
+ # udp !HHHH
+ u_buf = b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x28' \
+ + b'\x00\x00'
+
+ buf = e_buf + ip_buf + u_buf + self.payload
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv6 = protocols['ipv6']
+ p_udp = protocols['udp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_('ff:ff:ff:ff:ff:ff', p_eth.dst)
+ eq_('00:00:00:00:00:00', p_eth.src)
+ eq_(ether.ETH_TYPE_IPV6, p_eth.ethertype)
+
+ # ipv6
+ ok_(p_ipv6)
+ eq_(6, p_ipv6.version)
+ eq_(0, p_ipv6.traffic_class)
+ eq_(0, p_ipv6.flow_label)
+ eq_(len(u_buf) + len(self.payload), p_ipv6.payload_length)
+ eq_(inet.IPPROTO_UDP, p_ipv6.nxt)
+ eq_(255, p_ipv6.hop_limit)
+ eq_('10::10', p_ipv6.src)
+ eq_('20::20', p_ipv6.dst)
+
+ # udp
+ ok_(p_udp)
+ eq_(1, p_udp.src_port)
+ eq_(1, p_udp.dst_port)
+ eq_(len(u_buf) + len(self.payload), p_udp.total_length)
+ eq_(0x2B60, p_udp.csum)
+ t = bytearray(u_buf)
+ struct.pack_into('!H', t, 6, p_udp.csum)
+ ph = struct.pack('!16s16sI3xB', ipaddr, ipaddr,
+ len(u_buf) + len(self.payload), 17)
+ t = ph + t + self.payload
+ eq_(packet_utils.checksum(t), 0x62)
+
+ # payload
+ ok_('payload' in protocols)
+ eq_(self.payload, protocols['payload'])
+
+ # to string
+ eth_values = {'dst': 'ff:ff:ff:ff:ff:ff',
+ 'src': '00:00:00:00:00:00',
+ 'ethertype': ether.ETH_TYPE_IPV6}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv6_values = {'version': 6,
+ 'traffic_class': 0,
+ 'flow_label': 0,
+ 'payload_length': len(u_buf) + len(self.payload),
+ 'nxt': inet.IPPROTO_UDP,
+ 'hop_limit': 255,
+ 'src': '10::10',
+ 'dst': '20::20',
+ 'ext_hdrs': []}
+ _ipv6_str = ','.join(['%s=%s' % (k, repr(ipv6_values[k]))
+ for k, v in inspect.getmembers(p_ipv6)
+ if k in ipv6_values])
+ ipv6_str = '%s(%s)' % (ipv6.ipv6.__name__, _ipv6_str)
+
+ udp_values = {'src_port': 1,
+ 'dst_port': 1,
+ 'total_length': len(u_buf) + len(self.payload),
+ 'csum': 0x2B60}
+ _udp_str = ','.join(['%s=%s' % (k, repr(udp_values[k]))
+ for k, v in inspect.getmembers(p_udp)
+ if k in udp_values])
+ udp_str = '%s(%s)' % (udp.udp.__name__, _udp_str)
+
+ pkt_str = '%s, %s, %s, %s' % (eth_str, ipv6_str, udp_str,
+ repr(protocols['payload']))
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv6_str, str(p_ipv6))
+ eq_(ipv6_str, repr(p_ipv6))
+
+ eq_(udp_str, str(p_udp))
+ eq_(udp_str, repr(p_udp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv6_tcp(self):
+ # build packet
+ e = ethernet.ethernet(ethertype=ether.ETH_TYPE_IPV6)
+ ip = ipv6.ipv6()
+ t = tcp.tcp(option=b'\x01\x02')
+
+ p = e / ip / t / self.payload
+ p.serialize()
+
+ ipaddr = addrconv.ipv6.text_to_bin('::')
+
+ # ethernet !6s6sH
+ e_buf = b'\xff\xff\xff\xff\xff\xff' \
+ + b'\x00\x00\x00\x00\x00\x00' \
+ + b'\x86\xdd'
+
+ # ipv6 !IHBB16s16s'
+ ip_buf = b'\x60\x00\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x06' \
+ + b'\xff' \
+ + b'\x00\x00' \
+ + ipaddr \
+ + ipaddr
+
+ # tcp !HHIIBBHHH + option
+ t_buf = b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x60' \
+ + b'\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x01\x02\x00\x00'
+
+ buf = e_buf + ip_buf + t_buf + self.payload
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv6 = protocols['ipv6']
+ p_tcp = protocols['tcp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_('ff:ff:ff:ff:ff:ff', p_eth.dst)
+ eq_('00:00:00:00:00:00', p_eth.src)
+ eq_(ether.ETH_TYPE_IPV6, p_eth.ethertype)
+
+ # ipv6
+ ok_(p_ipv6)
+ eq_(6, p_ipv6.version)
+ eq_(0, p_ipv6.traffic_class)
+ eq_(0, p_ipv6.flow_label)
+ eq_(len(t_buf) + len(self.payload), p_ipv6.payload_length)
+ eq_(inet.IPPROTO_TCP, p_ipv6.nxt)
+ eq_(255, p_ipv6.hop_limit)
+ eq_('10::10', p_ipv6.src)
+ eq_('20::20', p_ipv6.dst)
+
+ # tcp
+ ok_(p_tcp)
+ eq_(1, p_tcp.src_port)
+ eq_(1, p_tcp.dst_port)
+ eq_(0, p_tcp.seq)
+ eq_(0, p_tcp.ack)
+ eq_(6, p_tcp.offset)
+ eq_(0, p_tcp.bits)
+ eq_(0, p_tcp.window_size)
+ eq_(0, p_tcp.urgent)
+ eq_(len(t_buf), len(p_tcp))
+ t = bytearray(t_buf)
+ struct.pack_into('!H', t, 16, p_tcp.csum)
+ ph = struct.pack('!16s16sI3xB', ipaddr, ipaddr,
+ len(t_buf) + len(self.payload), 6)
+ t = ph + t + self.payload
+ eq_(packet_utils.checksum(t), 0x62)
+
+ # payload
+ ok_('payload' in protocols)
+ eq_(self.payload, protocols['payload'])
+
+ # to string
+ eth_values = {'dst': 'ff:ff:ff:ff:ff:ff',
+ 'src': '00:00:00:00:00:00',
+ 'ethertype': ether.ETH_TYPE_IPV6}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv6_values = {'version': 6,
+ 'traffic_class': 0,
+ 'flow_label': 0,
+ 'payload_length': len(t_buf) + len(self.payload),
+ 'nxt': inet.IPPROTO_TCP,
+ 'hop_limit': 255,
+ 'src': '10::10',
+ 'dst': '20::20',
+ 'ext_hdrs': []}
+ _ipv6_str = ','.join(['%s=%s' % (k, repr(ipv6_values[k]))
+ for k, v in inspect.getmembers(p_ipv6)
+ if k in ipv6_values])
+ ipv6_str = '%s(%s)' % (ipv6.ipv6.__name__, _ipv6_str)
+
+ tcp_values = {'src_port': 1,
+ 'dst_port': 1,
+ 'seq': 0,
+ 'ack': 0,
+ 'offset': 6,
+ 'bits': 0,
+ 'window_size': 0,
+ 'csum': p_tcp.csum,
+ 'urgent': 0,
+ 'option': p_tcp.option}
+ _tcp_str = ','.join(['%s=%s' % (k, repr(tcp_values[k]))
+ for k, v in inspect.getmembers(p_tcp)
+ if k in tcp_values])
+ tcp_str = '%s(%s)' % (tcp.tcp.__name__, _tcp_str)
+
+ pkt_str = '%s, %s, %s, %s' % (eth_str, ipv6_str, tcp_str,
+ repr(protocols['payload']))
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv6_str, str(p_ipv6))
+ eq_(ipv6_str, repr(p_ipv6))
+
+ eq_(tcp_str, str(p_tcp))
+ eq_(tcp_str, repr(p_tcp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv6_sctp(self):
+ # build packet
+ e = ethernet.ethernet(ethertype=ether.ETH_TYPE_IPV6)
+ ip = ipv6.ipv6(nxt=inet.IPPROTO_SCTP)
+ s = sctp.sctp(chunks=[sctp.chunk_data(payload_data=self.payload)])
+
+ p = e / ip / s
+ p.serialize()
+
+ ipaddr = addrconv.ipv6.text_to_bin('::')
+
+ # ethernet !6s6sH
+ e_buf = b'\xff\xff\xff\xff\xff\xff' \
+ + b'\x00\x00\x00\x00\x00\x00' \
+ + b'\x86\xdd'
+
+ # ipv6 !IHBB16s16s'
+ ip_buf = b'\x60\x00\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x84' \
+ + b'\xff' \
+ + b'\x00\x00' \
+ + ipaddr \
+ + ipaddr
+
+ # sctp !HHII + chunk_data !BBHIHHI + payload
+ s_buf = b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00' \
+ + b'\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x00\x00\x00\x00' \
+ + self.payload
+
+ buf = e_buf + ip_buf + s_buf
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv6 = protocols['ipv6']
+ p_sctp = protocols['sctp']
+
+ # ethernet
+ ok_(p_eth)
+ eq_('ff:ff:ff:ff:ff:ff', p_eth.dst)
+ eq_('00:00:00:00:00:00', p_eth.src)
+ eq_(ether.ETH_TYPE_IPV6, p_eth.ethertype)
+
+ # ipv6
+ ok_(p_ipv6)
+ eq_(6, p_ipv6.version)
+ eq_(0, p_ipv6.traffic_class)
+ eq_(0, p_ipv6.flow_label)
+ eq_(len(s_buf), p_ipv6.payload_length)
+ eq_(inet.IPPROTO_SCTP, p_ipv6.nxt)
+ eq_(255, p_ipv6.hop_limit)
+ eq_('10::10', p_ipv6.src)
+ eq_('20::20', p_ipv6.dst)
+
+ # sctp
+ ok_(p_sctp)
+ eq_(1, p_sctp.src_port)
+ eq_(1, p_sctp.dst_port)
+ eq_(0, p_sctp.vtag)
+ assert isinstance(p_sctp.chunks[0], sctp.chunk_data)
+ eq_(0, p_sctp.chunks[0]._type)
+ eq_(0, p_sctp.chunks[0].unordered)
+ eq_(0, p_sctp.chunks[0].begin)
+ eq_(0, p_sctp.chunks[0].end)
+ eq_(16 + len(self.payload), p_sctp.chunks[0].length)
+ eq_(0, p_sctp.chunks[0].tsn)
+ eq_(0, p_sctp.chunks[0].sid)
+ eq_(0, p_sctp.chunks[0].seq)
+ eq_(0, p_sctp.chunks[0].payload_id)
+ eq_(self.payload, p_sctp.chunks[0].payload_data)
+ eq_(len(s_buf), len(p_sctp))
+
+ # to string
+ eth_values = {'dst': 'ff:ff:ff:ff:ff:ff',
+ 'src': '00:00:00:00:00:00',
+ 'ethertype': ether.ETH_TYPE_IPV6}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv6_values = {'version': 6,
+ 'traffic_class': 0,
+ 'flow_label': 0,
+ 'payload_length': len(s_buf),
+ 'nxt': inet.IPPROTO_SCTP,
+ 'hop_limit': 255,
+ 'src': '10::10',
+ 'dst': '20::20',
+ 'ext_hdrs': []}
+ _ipv6_str = ','.join(['%s=%s' % (k, repr(ipv6_values[k]))
+ for k, v in inspect.getmembers(p_ipv6)
+ if k in ipv6_values])
+ ipv6_str = '%s(%s)' % (ipv6.ipv6.__name__, _ipv6_str)
+
+ data_values = {'unordered': 0,
+ 'begin': 0,
+ 'end': 0,
+ 'length': 16 + len(self.payload),
+ 'tsn': 0,
+ 'sid': 0,
+ 'seq': 0,
+ 'payload_id': 0,
+ 'payload_data': self.payload}
+ _data_str = ','.join(['%s=%s' % (k, repr(data_values[k]))
+ for k in sorted(data_values.keys())])
+ data_str = '[%s(%s)]' % (sctp.chunk_data.__name__, _data_str)
+
+ sctp_values = {'src_port': 1,
+ 'dst_port': 1,
+ 'vtag': 0,
+ 'csum': repr(p_sctp.csum),
+ 'chunks': data_str}
+ _sctp_str = ','.join(['%s=%s' % (k, sctp_values[k])
+ for k, _ in inspect.getmembers(p_sctp)
+ if k in sctp_values])
+ sctp_str = '%s(%s)' % (sctp.sctp.__name__, _sctp_str)
+
+ pkt_str = '%s, %s, %s' % (eth_str, ipv6_str, sctp_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv6_str, str(p_ipv6))
+ eq_(ipv6_str, repr(p_ipv6))
+
+ eq_(sctp_str, str(p_sctp))
+ eq_(sctp_str, repr(p_sctp))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_ipv6_icmpv6(self):
+ # build packet
+ e = ethernet.ethernet(ethertype=ether.ETH_TYPE_IPV6)
+ ip = ipv6.ipv6(nxt=inet.IPPROTO_ICMPV6)
+ ic = icmpv6.icmpv6()
+
+ p = e / ip / ic
+ p.serialize()
+
+ ipaddr = addrconv.ipv6.text_to_bin('::')
+
+ # ethernet !6s6sH
+ e_buf = b'\xff\xff\xff\xff\xff\xff' \
+ + b'\x00\x00\x00\x00\x00\x00' \
+ + b'\x86\xdd'
+
+ # ipv6 !IHBB16s16s'
+ ip_buf = b'\x60\x00\x00\x00' \
+ + b'\x00\x00' \
+ + b'\x3a' \
+ + b'\xff' \
+ + b'\x00\x00' \
+ + ipaddr \
+ + ipaddr
+
+ # icmpv6 !BBH
+ ic_buf = b'\x00' \
+ + b'\x00' \
+ + b'\x00\x00'
+
+ buf = e_buf + ip_buf + ic_buf
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_ipv6 = protocols['ipv6']
+ p_icmpv6 = protocols['icmpv6']
+
+ # ethernet
+ ok_(p_eth)
+ eq_('ff:ff:ff:ff:ff:ff', p_eth.dst)
+ eq_('00:00:00:00:00:00', p_eth.src)
+ eq_(ether.ETH_TYPE_IPV6, p_eth.ethertype)
+
+ # ipv6
+ ok_(p_ipv6)
+ eq_(6, p_ipv6.version)
+ eq_(0, p_ipv6.traffic_class)
+ eq_(0, p_ipv6.flow_label)
+ eq_(len(ic_buf), p_ipv6.payload_length)
+ eq_(inet.IPPROTO_ICMPV6, p_ipv6.nxt)
+ eq_(255, p_ipv6.hop_limit)
+ eq_('10::10', p_ipv6.src)
+ eq_('20::20', p_ipv6.dst)
+
+ # icmpv6
+ ok_(p_icmpv6)
+ eq_(0, p_icmpv6.type_)
+ eq_(0, p_icmpv6.code)
+ eq_(len(ic_buf), len(p_icmpv6))
+ t = bytearray(ic_buf)
+ struct.pack_into('!H', t, 2, p_icmpv6.csum)
+ ph = struct.pack('!16s16sI3xB', ipaddr, ipaddr, len(ic_buf), 58)
+ t = ph + t
+ eq_(packet_utils.checksum(t), 0x60)
+
+ # to string
+ eth_values = {'dst': 'ff:ff:ff:ff:ff:ff',
+ 'src': '00:00:00:00:00:00',
+ 'ethertype': ether.ETH_TYPE_IPV6}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, _ in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ipv6_values = {'version': 6,
+ 'traffic_class': 0,
+ 'flow_label': 0,
+ 'payload_length': len(ic_buf),
+ 'nxt': inet.IPPROTO_ICMPV6,
+ 'hop_limit': 255,
+ 'src': '10::10',
+ 'dst': '20::20',
+ 'ext_hdrs': []}
+ _ipv6_str = ','.join(['%s=%s' % (k, repr(ipv6_values[k]))
+ for k, _ in inspect.getmembers(p_ipv6)
+ if k in ipv6_values])
+ ipv6_str = '%s(%s)' % (ipv6.ipv6.__name__, _ipv6_str)
+
+ icmpv6_values = {'type_': 0,
+ 'code': 0,
+ 'csum': p_icmpv6.csum,
+ 'data': None}
+ _icmpv6_str = ','.join(['%s=%s' % (k, repr(icmpv6_values[k]))
+ for k, _ in inspect.getmembers(p_icmpv6)
+ if k in icmpv6_values])
+ icmpv6_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _icmpv6_str)
+
+ pkt_str = '%s, %s, %s' % (eth_str, ipv6_str, icmpv6_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(ipv6_str, str(p_ipv6))
+ eq_(ipv6_str, repr(p_ipv6))
+
+ eq_(icmpv6_str, str(p_icmpv6))
+ eq_(icmpv6_str, repr(p_icmpv6))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_llc_bpdu(self):
+ # buid packet
+ e = ethernet.ethernet(self.dst_mac, self.src_mac,
+ ether.ETH_TYPE_IEEE802_3)
+ llc_control = llc.ControlFormatU(0, 0, 0)
+ l = llc.llc(llc.SAP_BPDU, llc.SAP_BPDU, llc_control)
+ b = bpdu.ConfigurationBPDUs(flags=0,
+ root_priority=32768,
+ root_system_id_extension=0,
+ root_mac_address=self.src_mac,
+ root_path_cost=0,
+ bridge_priority=32768,
+ bridge_system_id_extension=0,
+ bridge_mac_address=self.dst_mac,
+ port_priority=128,
+ port_number=4,
+ message_age=1,
+ max_age=20,
+ hello_time=2,
+ forward_delay=15)
+
+ p = packet.Packet()
+ p.add_protocol(e)
+ p.add_protocol(l)
+ p.add_protocol(b)
+ p.serialize()
+
+ # ethernet !6s6sH
+ e_buf = self.dst_mac_bin + self.src_mac_bin + b'\x05\xdc'
+
+ # llc !BBB
+ l_buf = (b'\x42'
+ b'\x42'
+ b'\x03')
+
+ # bpdu !HBBBQIQHHHHH
+ b_buf = (b'\x00\x00'
+ b'\x00'
+ b'\x00'
+ b'\x00'
+ b'\x80\x00\xbb\xbb\xbb\xbb\xbb\xbb'
+ b'\x00\x00\x00\x00'
+ b'\x80\x00\xaa\xaa\xaa\xaa\xaa\xaa'
+ b'\x80\x04'
+ b'\x01\x00'
+ b'\x14\x00'
+ b'\x02\x00'
+ b'\x0f\x00')
+
+ buf = e_buf + l_buf + b_buf
+
+ # Append padding if ethernet frame is less than 60 bytes length
+ pad_len = 60 - len(buf)
+ if pad_len > 0:
+ buf += b'\x00' * pad_len
+ eq_(buf, p.data)
+
+ # parse
+ pkt = packet.Packet(p.data)
+ protocols = self.get_protocols(pkt)
+ p_eth = protocols['ethernet']
+ p_llc = protocols['llc']
+ p_bpdu = protocols['ConfigurationBPDUs']
+
+ # ethernet
+ ok_(p_eth)
+ eq_(self.dst_mac, p_eth.dst)
+ eq_(self.src_mac, p_eth.src)
+ eq_(ether.ETH_TYPE_IEEE802_3, p_eth.ethertype)
+
+ # llc
+ ok_(p_llc)
+ eq_(llc.SAP_BPDU, p_llc.dsap_addr)
+ eq_(llc.SAP_BPDU, p_llc.ssap_addr)
+ eq_(0, p_llc.control.modifier_function1)
+ eq_(0, p_llc.control.pf_bit)
+ eq_(0, p_llc.control.modifier_function2)
+
+ # bpdu
+ ok_(p_bpdu)
+ eq_(bpdu.PROTOCOL_IDENTIFIER, p_bpdu._protocol_id)
+ eq_(bpdu.PROTOCOLVERSION_ID_BPDU, p_bpdu._version_id)
+ eq_(bpdu.TYPE_CONFIG_BPDU, p_bpdu._bpdu_type)
+ eq_(0, p_bpdu.flags)
+ eq_(32768, p_bpdu.root_priority)
+ eq_(0, p_bpdu.root_system_id_extension)
+ eq_(self.src_mac, p_bpdu.root_mac_address)
+ eq_(0, p_bpdu.root_path_cost)
+ eq_(32768, p_bpdu.bridge_priority)
+ eq_(0, p_bpdu.bridge_system_id_extension)
+ eq_(self.dst_mac, p_bpdu.bridge_mac_address)
+ eq_(128, p_bpdu.port_priority)
+ eq_(4, p_bpdu.port_number)
+ eq_(1, p_bpdu.message_age)
+ eq_(20, p_bpdu.max_age)
+ eq_(2, p_bpdu.hello_time)
+ eq_(15, p_bpdu.forward_delay)
+
+ # to string
+ eth_values = {'dst': self.dst_mac,
+ 'src': self.src_mac,
+ 'ethertype': ether.ETH_TYPE_IEEE802_3}
+ _eth_str = ','.join(['%s=%s' % (k, repr(eth_values[k]))
+ for k, v in inspect.getmembers(p_eth)
+ if k in eth_values])
+ eth_str = '%s(%s)' % (ethernet.ethernet.__name__, _eth_str)
+
+ ctrl_values = {'modifier_function1': 0,
+ 'pf_bit': 0,
+ 'modifier_function2': 0}
+ _ctrl_str = ','.join(['%s=%s' % (k, repr(ctrl_values[k]))
+ for k, v in inspect.getmembers(p_llc.control)
+ if k in ctrl_values])
+ ctrl_str = '%s(%s)' % (llc.ControlFormatU.__name__, _ctrl_str)
+
+ llc_values = {'dsap_addr': repr(llc.SAP_BPDU),
+ 'ssap_addr': repr(llc.SAP_BPDU),
+ 'control': ctrl_str}
+ _llc_str = ','.join(['%s=%s' % (k, llc_values[k])
+ for k, v in inspect.getmembers(p_llc)
+ if k in llc_values])
+ llc_str = '%s(%s)' % (llc.llc.__name__, _llc_str)
+
+ _long = int if six.PY3 else long
+ bpdu_values = {'flags': 0,
+ 'root_priority': _long(32768),
+ 'root_system_id_extension': _long(0),
+ 'root_mac_address': self.src_mac,
+ 'root_path_cost': 0,
+ 'bridge_priority': _long(32768),
+ 'bridge_system_id_extension': _long(0),
+ 'bridge_mac_address': self.dst_mac,
+ 'port_priority': 128,
+ 'port_number': 4,
+ 'message_age': float(1),
+ 'max_age': float(20),
+ 'hello_time': float(2),
+ 'forward_delay': float(15)}
+ _bpdu_str = ','.join(['%s=%s' % (k, repr(bpdu_values[k]))
+ for k, v in inspect.getmembers(p_bpdu)
+ if k in bpdu_values])
+ bpdu_str = '%s(%s)' % (bpdu.ConfigurationBPDUs.__name__, _bpdu_str)
+
+ pkt_str = '%s, %s, %s' % (eth_str, llc_str, bpdu_str)
+
+ eq_(eth_str, str(p_eth))
+ eq_(eth_str, repr(p_eth))
+
+ eq_(llc_str, str(p_llc))
+ eq_(llc_str, repr(p_llc))
+
+ eq_(bpdu_str, str(p_bpdu))
+ eq_(bpdu_str, repr(p_bpdu))
+
+ eq_(pkt_str, str(pkt))
+ eq_(pkt_str, repr(pkt))
+
+ def test_div_api(self):
+ e = ethernet.ethernet(self.dst_mac, self.src_mac, ether.ETH_TYPE_IP)
+ i = ipv4.ipv4()
+ u = udp.udp(self.src_port, self.dst_port)
+ pkt = e / i / u
+ ok_(isinstance(pkt, packet.Packet))
+ ok_(isinstance(pkt.protocols[0], ethernet.ethernet))
+ ok_(isinstance(pkt.protocols[1], ipv4.ipv4))
+ ok_(isinstance(pkt.protocols[2], udp.udp))
diff --git a/tests/unit/packet/test_pbb.py b/tests/unit/packet/test_pbb.py
new file mode 100644
index 00000000..dd7778cd
--- /dev/null
+++ b/tests/unit/packet/test_pbb.py
@@ -0,0 +1,172 @@
+# Copyright (C) 2013 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
+import unittest
+
+from nose.tools import eq_
+from nose.tools import ok_
+from nose.tools import raises
+from ryu.ofproto import ether
+from ryu.ofproto import inet
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import packet
+from ryu.lib.packet import ipv4
+from ryu.lib.packet import vlan
+from ryu.lib.packet import pbb
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_itag(unittest.TestCase):
+
+ pcp = 3
+ dei = 0
+ uca = 1
+ sid = 16770000
+ data = pcp << 29 | dei << 28 | uca << 27 | sid
+ buf = struct.pack(pbb.itag._PACK_STR, data)
+ it = pbb.itag(pcp, dei, uca, sid)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.pcp, self.it.pcp)
+ eq_(self.dei, self.it.dei)
+ eq_(self.uca, self.it.uca)
+ eq_(self.sid, self.it.sid)
+
+ def test_parser(self):
+ _res = pbb.itag.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ eq_(res.pcp, self.pcp)
+ eq_(res.dei, self.dei)
+ eq_(res.uca, self.uca)
+ eq_(res.sid, self.sid)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.it.serialize(data, prev)
+ res = struct.unpack(pbb.itag._PACK_STR, buf)
+ eq_(res[0], self.data)
+
+ def _build_itag(self):
+ b_src_mac = '00:07:0d:af:f4:54'
+ b_dst_mac = '00:00:00:00:00:00'
+ b_ethertype = ether.ETH_TYPE_8021AD
+ e1 = ethernet.ethernet(b_dst_mac, b_src_mac, b_ethertype)
+
+ b_pcp = 0
+ b_cfi = 0
+ b_vid = 32
+ b_ethertype = ether.ETH_TYPE_8021Q
+ bt = vlan.svlan(b_pcp, b_cfi, b_vid, b_ethertype)
+
+ c_src_mac = '11:11:11:11:11:11'
+ c_dst_mac = 'aa:aa:aa:aa:aa:aa'
+ c_ethertype = ether.ETH_TYPE_8021AD
+ e2 = ethernet.ethernet(c_dst_mac, c_src_mac, c_ethertype)
+
+ s_pcp = 0
+ s_cfi = 0
+ s_vid = 32
+ s_ethertype = ether.ETH_TYPE_8021Q
+ st = vlan.svlan(s_pcp, s_cfi, s_vid, s_ethertype)
+
+ c_pcp = 0
+ c_cfi = 0
+ c_vid = 32
+ c_ethertype = ether.ETH_TYPE_IP
+ ct = vlan.vlan(c_pcp, c_cfi, c_vid, c_ethertype)
+
+ version = 4
+ header_length = 20
+ tos = 0
+ total_length = 24
+ identification = 0x8a5d
+ flags = 0
+ offset = 1480
+ ttl = 64
+ proto = inet.IPPROTO_ICMP
+ csum = 0xa7f2
+ src = '131.151.32.21'
+ dst = '131.151.32.129'
+ option = b'TEST'
+ ip = ipv4.ipv4(version, header_length, tos, total_length,
+ identification, flags, offset, ttl, proto, csum,
+ src, dst, option)
+
+ p = packet.Packet()
+
+ p.add_protocol(e1)
+ p.add_protocol(bt)
+ p.add_protocol(self.it)
+ p.add_protocol(e2)
+ p.add_protocol(st)
+ p.add_protocol(ct)
+ p.add_protocol(ip)
+ p.serialize()
+
+ return p
+
+ def test_build_itag(self):
+ p = self._build_itag()
+
+ e = p.get_protocols(ethernet.ethernet)
+ ok_(e)
+ ok_(isinstance(e, list))
+ eq_(e[0].ethertype, ether.ETH_TYPE_8021AD)
+ eq_(e[1].ethertype, ether.ETH_TYPE_8021AD)
+
+ sv = p.get_protocols(vlan.svlan)
+ ok_(sv)
+ ok_(isinstance(sv, list))
+ eq_(sv[0].ethertype, ether.ETH_TYPE_8021Q)
+ eq_(sv[1].ethertype, ether.ETH_TYPE_8021Q)
+
+ it = p.get_protocol(pbb.itag)
+ ok_(it)
+
+ v = p.get_protocol(vlan.vlan)
+ ok_(v)
+ eq_(v.ethertype, ether.ETH_TYPE_IP)
+
+ ip = p.get_protocol(ipv4.ipv4)
+ ok_(ip)
+
+ eq_(it.pcp, self.pcp)
+ eq_(it.dei, self.dei)
+ eq_(it.uca, self.uca)
+ eq_(it.sid, self.sid)
+
+ @raises(Exception)
+ def test_malformed_itag(self):
+ m_short_buf = self.buf[1:pbb.itag._MIN_LEN]
+ pbb.itag.parser(m_short_buf)
+
+ def test_json(self):
+ jsondict = self.it.to_jsondict()
+ it = pbb.itag.from_jsondict(jsondict['itag'])
+ eq_(str(self.it), str(it))
diff --git a/tests/unit/packet/test_sctp.py b/tests/unit/packet/test_sctp.py
new file mode 100644
index 00000000..d7afb7cc
--- /dev/null
+++ b/tests/unit/packet/test_sctp.py
@@ -0,0 +1,1454 @@
+# Copyright (C) 2013 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 inspect
+import logging
+import six
+import struct
+import unittest
+
+from nose.tools import eq_
+from nose.tools import ok_
+from ryu.lib import addrconv
+from ryu.lib.packet import packet
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import ipv4
+from ryu.lib.packet import sctp
+from ryu.ofproto import ether
+from ryu.ofproto import inet
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_sctp(unittest.TestCase):
+
+ def setUp(self):
+ self.chunks = []
+ self.csum = 0
+ self.dst_port = 1234
+ self.src_port = 5678
+ self.vtag = 98765432
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf = b'\x16\x2e\x04\xd2\x05\xe3\x0a\x78\x00\x00\x00\x00'
+
+ def setUp_with_data(self):
+ self.unordered = 1
+ self.begin = 1
+ self.end = 1
+ self.length = 16 + 10
+ self.tsn = 12345
+ self.sid = 1
+ self.seq = 0
+ self.payload_id = 0
+ self.payload_data = b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a'
+
+ self.data = sctp.chunk_data(
+ unordered=self.unordered, begin=self.begin, end=self.end,
+ tsn=self.tsn, sid=self.sid, payload_data=self.payload_data)
+
+ self.chunks = [self.data]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x00\x07\x00\x1a\x00\x00\x30\x39\x00\x01\x00\x00' + \
+ b'\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a'
+
+ def setUp_with_init(self):
+ self.flags = 0
+ self.length = 20 + 8 + 20 + 8 + 4 + 16 + 16
+ self.init_tag = 123456
+ self.a_rwnd = 9876
+ self.os = 3
+ self.mis = 3
+ self.i_tsn = 123456
+
+ self.p_ipv4 = sctp.param_ipv4('192.168.1.1')
+ self.p_ipv6 = sctp.param_ipv6('fe80::647e:1aff:fec4:8284')
+ self.p_cookie_preserve = sctp.param_cookie_preserve(5000)
+ self.p_ecn = sctp.param_ecn()
+ self.p_host_addr = sctp.param_host_addr(b'test host\x00')
+ self.p_support_type = sctp.param_supported_addr(
+ [sctp.PTYPE_IPV4, sctp.PTYPE_IPV6, sctp.PTYPE_COOKIE_PRESERVE,
+ sctp.PTYPE_ECN, sctp.PTYPE_HOST_ADDR])
+ self.params = [
+ self.p_ipv4, self.p_ipv6, self.p_cookie_preserve,
+ self.p_ecn, self.p_host_addr, self.p_support_type]
+
+ self.init = sctp.chunk_init(
+ init_tag=self.init_tag, a_rwnd=self.a_rwnd, os=self.os,
+ mis=self.mis, i_tsn=self.i_tsn, params=self.params)
+
+ self.chunks = [self.init]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x01\x00\x00\x5c\x00\x01\xe2\x40\x00\x00\x26\x94' + \
+ b'\x00\x03\x00\x03\x00\x01\xe2\x40' + \
+ b'\x00\x05\x00\x08\xc0\xa8\x01\x01' + \
+ b'\x00\x06\x00\x14' + \
+ b'\xfe\x80\x00\x00\x00\x00\x00\x00' + \
+ b'\x64\x7e\x1a\xff\xfe\xc4\x82\x84' + \
+ b'\x00\x09\x00\x08\x00\x00\x13\x88' + \
+ b'\x80\x00\x00\x04' + \
+ b'\x00\x0b\x00\x0e' + \
+ b'\x74\x65\x73\x74\x20\x68\x6f\x73\x74\x00\x00\x00' + \
+ b'\x00\x0c\x00\x0e\x00\x05\x00\x06\x00\x09\x80\x00' + \
+ b'\x00\x0b\x00\x00'
+
+ def setUp_with_init_ack(self):
+ self.flags = 0
+ self.length = 20 + 8 + 8 + 20 + 8 + 4 + 16
+ self.init_tag = 123456
+ self.a_rwnd = 9876
+ self.os = 3
+ self.mis = 3
+ self.i_tsn = 123456
+
+ self.p_state_cookie = sctp.param_state_cookie(b'\x01\x02\x03')
+ self.p_ipv4 = sctp.param_ipv4('192.168.1.1')
+ self.p_ipv6 = sctp.param_ipv6('fe80::647e:1aff:fec4:8284')
+ self.p_unrecognized_param = sctp.param_unrecognized_param(
+ b'\xff\xff\x00\x04')
+ self.p_ecn = sctp.param_ecn()
+ self.p_host_addr = sctp.param_host_addr(b'test host\x00')
+ self.params = [
+ self.p_state_cookie, self.p_ipv4, self.p_ipv6,
+ self.p_unrecognized_param, self.p_ecn, self.p_host_addr]
+
+ self.init_ack = sctp.chunk_init_ack(
+ init_tag=self.init_tag, a_rwnd=self.a_rwnd, os=self.os,
+ mis=self.mis, i_tsn=self.i_tsn, params=self.params)
+
+ self.chunks = [self.init_ack]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x02\x00\x00\x54\x00\x01\xe2\x40\x00\x00\x26\x94' + \
+ b'\x00\x03\x00\x03\x00\x01\xe2\x40' + \
+ b'\x00\x07\x00\x07\x01\x02\x03\x00' + \
+ b'\x00\x05\x00\x08\xc0\xa8\x01\x01' + \
+ b'\x00\x06\x00\x14' + \
+ b'\xfe\x80\x00\x00\x00\x00\x00\x00' + \
+ b'\x64\x7e\x1a\xff\xfe\xc4\x82\x84' + \
+ b'\x00\x08\x00\x08\xff\xff\x00\x04' + \
+ b'\x80\x00\x00\x04' + \
+ b'\x00\x0b\x00\x0e' + \
+ b'\x74\x65\x73\x74\x20\x68\x6f\x73\x74\x00\x00\x00'
+
+ def setUp_with_sack(self):
+ self.flags = 0
+ self.length = 16 + 2 * 2 * 5 + 4 * 5
+ self.tsn_ack = 123456
+ self.a_rwnd = 9876
+ self.gapack_num = 5
+ self.duptsn_num = 5
+ self.gapacks = [[2, 3], [10, 12], [20, 24], [51, 52], [62, 63]]
+ self.duptsns = [123458, 123466, 123476, 123507, 123518]
+
+ self.sack = sctp.chunk_sack(
+ tsn_ack=self.tsn_ack, a_rwnd=self.a_rwnd,
+ gapack_num=self.gapack_num, duptsn_num=self.duptsn_num,
+ gapacks=self.gapacks, duptsns=self.duptsns)
+
+ self.chunks = [self.sack]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x03\x00\x00\x38\x00\x01\xe2\x40' + \
+ b'\x00\x00\x26\x94\x00\x05\x00\x05' + \
+ b'\x00\x02\x00\x03\x00\x0a\x00\x0c\x00\x14\x00\x18' + \
+ b'\x00\x33\x00\x34\x00\x3e\x00\x3f' + \
+ b'\x00\x01\xe2\x42\x00\x01\xe2\x4a\x00\x01\xe2\x54' + \
+ b'\x00\x01\xe2\x73\x00\x01\xe2\x7e'
+
+ def setUp_with_heartbeat(self):
+ self.flags = 0
+ self.length = 4 + 8
+
+ self.p_heartbeat = sctp.param_heartbeat(b'\x01\x02\x03\x04')
+
+ self.heartbeat = sctp.chunk_heartbeat(info=self.p_heartbeat)
+
+ self.chunks = [self.heartbeat]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x04\x00\x00\x0c' + \
+ b'\x00\x01\x00\x08' + \
+ b'\x01\x02\x03\x04'
+
+ def setUp_with_heartbeat_ack(self):
+ self.flags = 0
+ self.length = 4 + 12
+
+ self.p_heartbeat = sctp.param_heartbeat(
+ b'\xff\xee\xdd\xcc\xbb\xaa\x99\x88')
+
+ self.heartbeat_ack = sctp.chunk_heartbeat_ack(info=self.p_heartbeat)
+
+ self.chunks = [self.heartbeat_ack]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x05\x00\x00\x10' + \
+ b'\x00\x01\x00\x0c' + \
+ b'\xff\xee\xdd\xcc\xbb\xaa\x99\x88'
+
+ def setUp_with_abort(self):
+ self.tflag = 0
+ self.length = 4 + 8 + 16 + 8 + 4 + 20 + 8 + 4 + 8 + 8 + 4 + 12 \
+ + 20 + 20
+
+ self.c_invalid_stream_id = sctp.cause_invalid_stream_id(4096)
+ self.c_missing_param = sctp.cause_missing_param(
+ [sctp.PTYPE_IPV4, sctp.PTYPE_IPV6,
+ sctp.PTYPE_COOKIE_PRESERVE, sctp.PTYPE_HOST_ADDR])
+ self.c_stale_cookie = sctp.cause_stale_cookie(b'\x00\x00\x13\x88')
+ self.c_out_of_resource = sctp.cause_out_of_resource()
+ self.c_unresolvable_addr = sctp.cause_unresolvable_addr(
+ sctp.param_host_addr(b'test host\x00'))
+ self.c_unrecognized_chunk = sctp.cause_unrecognized_chunk(
+ b'\xff\x00\x00\x04')
+ self.c_invalid_param = sctp.cause_invalid_param()
+ self.c_unrecognized_param = sctp.cause_unrecognized_param(
+ b'\xff\xff\x00\x04')
+ self.c_no_userdata = sctp.cause_no_userdata(b'\x00\x01\xe2\x40')
+ self.c_cookie_while_shutdown = sctp.cause_cookie_while_shutdown()
+ self.c_restart_with_new_addr = sctp.cause_restart_with_new_addr(
+ sctp.param_ipv4('192.168.1.1'))
+ self.c_user_initiated_abort = sctp.cause_user_initiated_abort(
+ b'Key Interrupt.\x00')
+ self.c_protocol_violation = sctp.cause_protocol_violation(
+ b'Unknown reason.\x00')
+
+ self.causes = [
+ self.c_invalid_stream_id, self.c_missing_param,
+ self.c_stale_cookie, self.c_out_of_resource,
+ self.c_unresolvable_addr, self.c_unrecognized_chunk,
+ self.c_invalid_param, self.c_unrecognized_param,
+ self.c_no_userdata, self.c_cookie_while_shutdown,
+ self.c_restart_with_new_addr, self.c_user_initiated_abort,
+ self.c_protocol_violation]
+
+ self.abort = sctp.chunk_abort(causes=self.causes)
+
+ self.chunks = [self.abort]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x06\x00\x00\x90' + \
+ b'\x00\x01\x00\x08\x10\x00\x00\x00' + \
+ b'\x00\x02\x00\x10\x00\x00\x00\x04' + \
+ b'\x00\x05\x00\x06\x00\x09\x00\x0b' + \
+ b'\x00\x03\x00\x08\x00\x00\x13\x88' + \
+ b'\x00\x04\x00\x04' + \
+ b'\x00\x05\x00\x14' + \
+ b'\x00\x0b\x00\x0e' + \
+ b'\x74\x65\x73\x74\x20\x68\x6f\x73\x74\x00\x00\x00' + \
+ b'\x00\x06\x00\x08\xff\x00\x00\x04' + \
+ b'\x00\x07\x00\x04' + \
+ b'\x00\x08\x00\x08\xff\xff\x00\x04' + \
+ b'\x00\x09\x00\x08\x00\x01\xe2\x40' + \
+ b'\x00\x0a\x00\x04' + \
+ b'\x00\x0b\x00\x0c' + \
+ b'\x00\x05\x00\x08\xc0\xa8\x01\x01' + \
+ b'\x00\x0c\x00\x13' + \
+ b'\x4b\x65\x79\x20\x49\x6e\x74\x65' + \
+ b'\x72\x72\x75\x70\x74\x2e\x00\x00' + \
+ b'\x00\x0d\x00\x14' + \
+ b'\x55\x6e\x6b\x6e\x6f\x77\x6e\x20' + \
+ b'\x72\x65\x61\x73\x6f\x6e\x2e\x00'
+
+ def setUp_with_shutdown(self):
+ self.flags = 0
+ self.length = 8
+ self.tsn_ack = 123456
+
+ self.shutdown = sctp.chunk_shutdown(tsn_ack=self.tsn_ack)
+
+ self.chunks = [self.shutdown]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x07\x00\x00\x08\x00\x01\xe2\x40'
+
+ def setUp_with_shutdown_ack(self):
+ self.flags = 0
+ self.length = 4
+
+ self.shutdown_ack = sctp.chunk_shutdown_ack()
+
+ self.chunks = [self.shutdown_ack]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x08\x00\x00\x04'
+
+ def setUp_with_error(self):
+ self.flags = 0
+ self.length = 4 + 8 + 16 + 8 + 4 + 20 + 8 + 4 + 8 + 8 + 4 + 12 \
+ + 20 + 20
+
+ self.c_invalid_stream_id = sctp.cause_invalid_stream_id(4096)
+ self.c_missing_param = sctp.cause_missing_param(
+ [sctp.PTYPE_IPV4, sctp.PTYPE_IPV6,
+ sctp.PTYPE_COOKIE_PRESERVE, sctp.PTYPE_HOST_ADDR])
+ self.c_stale_cookie = sctp.cause_stale_cookie(b'\x00\x00\x13\x88')
+ self.c_out_of_resource = sctp.cause_out_of_resource()
+ self.c_unresolvable_addr = sctp.cause_unresolvable_addr(
+ sctp.param_host_addr(b'test host\x00'))
+ self.c_unrecognized_chunk = sctp.cause_unrecognized_chunk(
+ b'\xff\x00\x00\x04')
+ self.c_invalid_param = sctp.cause_invalid_param()
+ self.c_unrecognized_param = sctp.cause_unrecognized_param(
+ b'\xff\xff\x00\x04')
+ self.c_no_userdata = sctp.cause_no_userdata(b'\x00\x01\xe2\x40')
+ self.c_cookie_while_shutdown = sctp.cause_cookie_while_shutdown()
+ self.c_restart_with_new_addr = sctp.cause_restart_with_new_addr(
+ sctp.param_ipv4('192.168.1.1'))
+ self.c_user_initiated_abort = sctp.cause_user_initiated_abort(
+ b'Key Interrupt.\x00')
+ self.c_protocol_violation = sctp.cause_protocol_violation(
+ b'Unknown reason.\x00')
+
+ self.causes = [
+ self.c_invalid_stream_id, self.c_missing_param,
+ self.c_stale_cookie, self.c_out_of_resource,
+ self.c_unresolvable_addr, self.c_unrecognized_chunk,
+ self.c_invalid_param, self.c_unrecognized_param,
+ self.c_no_userdata, self.c_cookie_while_shutdown,
+ self.c_restart_with_new_addr, self.c_user_initiated_abort,
+ self.c_protocol_violation]
+
+ self.error = sctp.chunk_error(causes=self.causes)
+
+ self.chunks = [self.error]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x09\x00\x00\x90' + \
+ b'\x00\x01\x00\x08\x10\x00\x00\x00' + \
+ b'\x00\x02\x00\x10\x00\x00\x00\x04' + \
+ b'\x00\x05\x00\x06\x00\x09\x00\x0b' + \
+ b'\x00\x03\x00\x08\x00\x00\x13\x88' + \
+ b'\x00\x04\x00\x04' + \
+ b'\x00\x05\x00\x14' + \
+ b'\x00\x0b\x00\x0e' + \
+ b'\x74\x65\x73\x74\x20\x68\x6f\x73\x74\x00\x00\x00' + \
+ b'\x00\x06\x00\x08\xff\x00\x00\x04' + \
+ b'\x00\x07\x00\x04' + \
+ b'\x00\x08\x00\x08\xff\xff\x00\x04' + \
+ b'\x00\x09\x00\x08\x00\x01\xe2\x40' + \
+ b'\x00\x0a\x00\x04' + \
+ b'\x00\x0b\x00\x0c' + \
+ b'\x00\x05\x00\x08\xc0\xa8\x01\x01' + \
+ b'\x00\x0c\x00\x13' + \
+ b'\x4b\x65\x79\x20\x49\x6e\x74\x65' + \
+ b'\x72\x72\x75\x70\x74\x2e\x00\x00' + \
+ b'\x00\x0d\x00\x14' + \
+ b'\x55\x6e\x6b\x6e\x6f\x77\x6e\x20' + \
+ b'\x72\x65\x61\x73\x6f\x6e\x2e\x00'
+
+ def setUp_with_cookie_echo(self):
+ self.flags = 0
+ self.length = 8
+ self.cookie = b'\x12\x34\x56\x78'
+
+ self.cookie_echo = sctp.chunk_cookie_echo(cookie=self.cookie)
+
+ self.chunks = [self.cookie_echo]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x0a\x00\x00\x08\x12\x34\x56\x78'
+
+ def setUp_with_cookie_ack(self):
+ self.flags = 0
+ self.length = 4
+
+ self.cookie_ack = sctp.chunk_cookie_ack()
+
+ self.chunks = [self.cookie_ack]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x0b\x00\x00\x04'
+
+ def setUp_with_ecn_echo(self):
+ self.flags = 0
+ self.length = 8
+ self.low_tsn = 123456
+
+ self.ecn_echo = sctp.chunk_ecn_echo(low_tsn=self.low_tsn)
+
+ self.chunks = [self.ecn_echo]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x0c\x00\x00\x08\x00\x01\xe2\x40'
+
+ def setUp_with_cwr(self):
+ self.flags = 0
+ self.length = 8
+ self.low_tsn = 123456
+
+ self.cwr = sctp.chunk_cwr(low_tsn=self.low_tsn)
+
+ self.chunks = [self.cwr]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x0d\x00\x00\x08\x00\x01\xe2\x40'
+
+ def setUp_with_shutdown_complete(self):
+ self.tflag = 0
+ self.length = 4
+
+ self.shutdown_complete = sctp.chunk_shutdown_complete()
+
+ self.chunks = [self.shutdown_complete]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x0e\x00\x00\x04'
+
+ def setUp_with_multi_chunks(self):
+ self.s_flags = 0
+ self.s_length = 16
+ self.s_tsn_ack = 123456
+ self.s_a_rwnd = 9876
+ self.s_gapack_num = 0
+ self.s_duptsn_num = 0
+ self.s_gapacks = None
+ self.s_duptsns = None
+
+ self.sack = sctp.chunk_sack(
+ tsn_ack=self.s_tsn_ack, a_rwnd=self.s_a_rwnd)
+
+ self.d1_unordered = 0
+ self.d1_begin = 1
+ self.d1_end = 0
+ self.d1_length = 16 + 10
+ self.d1_tsn = 12345
+ self.d1_sid = 1
+ self.d1_seq = 0
+ self.d1_payload_id = 0
+ self.d1_payload_data = b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a'
+
+ self.data1 = sctp.chunk_data(
+ begin=self.d1_begin, tsn=self.d1_tsn, sid=self.d1_sid,
+ payload_data=self.d1_payload_data)
+
+ self.d2_unordered = 0
+ self.d2_begin = 0
+ self.d2_end = 1
+ self.d2_length = 16 + 10
+ self.d2_tsn = 12346
+ self.d2_sid = 1
+ self.d2_seq = 1
+ self.d2_payload_id = 0
+ self.d2_payload_data = b'\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a'
+
+ self.data2 = sctp.chunk_data(
+ end=self.d2_end, tsn=self.d2_tsn, sid=self.d2_sid,
+ seq=self.d2_seq, payload_data=self.d2_payload_data)
+
+ self.chunks = [self.sack, self.data1, self.data2]
+
+ self.sc = sctp.sctp(
+ self.src_port, self.dst_port, self.vtag, self.csum,
+ self.chunks)
+
+ self.buf += b'\x03\x00\x00\x10\x00\x01\xe2\x40' + \
+ b'\x00\x00\x26\x94\x00\x00\x00\x00' + \
+ b'\x00\x02\x00\x1a\x00\x00\x30\x39\x00\x01\x00\x00' + \
+ b'\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a' + \
+ b'\x00\x01\x00\x1a\x00\x00\x30\x3a\x00\x01\x00\x01' + \
+ b'\x00\x00\x00\x00\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a'
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.src_port, self.sc.src_port)
+ eq_(self.dst_port, self.sc.dst_port)
+ eq_(self.vtag, self.sc.vtag)
+ eq_(self.csum, self.sc.csum)
+ eq_(self.chunks, self.sc.chunks)
+
+ def test_init_with_data(self):
+ self.setUp_with_data()
+ self.test_init()
+
+ def test_init_with_init(self):
+ self.setUp_with_init()
+ self.test_init()
+
+ def test_init_with_init_ack(self):
+ self.setUp_with_init_ack()
+ self.test_init()
+
+ def test_init_with_sack(self):
+ self.setUp_with_sack()
+ self.test_init()
+
+ def test_init_with_heartbeat(self):
+ self.setUp_with_heartbeat()
+ self.test_init()
+
+ def test_init_with_heartbeat_ack(self):
+ self.setUp_with_heartbeat_ack()
+ self.test_init()
+
+ def test_init_with_abort(self):
+ self.setUp_with_abort()
+ self.test_init()
+
+ def test_init_with_shutdown(self):
+ self.setUp_with_shutdown()
+ self.test_init()
+
+ def test_init_with_shutdown_ack(self):
+ self.setUp_with_shutdown_ack()
+ self.test_init()
+
+ def test_init_with_error(self):
+ self.setUp_with_error()
+ self.test_init()
+
+ def test_init_with_cookie_echo(self):
+ self.setUp_with_cookie_echo()
+ self.test_init()
+
+ def test_init_with_cookie_ack(self):
+ self.setUp_with_cookie_ack()
+ self.test_init()
+
+ def test_init_with_ecn_echo(self):
+ self.setUp_with_ecn_echo()
+ self.test_init()
+
+ def test_init_with_cwr(self):
+ self.setUp_with_cwr()
+ self.test_init()
+
+ def test_init_with_shutdown_complete(self):
+ self.setUp_with_shutdown_complete()
+ self.test_init()
+
+ def test_init_with_multi_chunks(self):
+ self.setUp_with_multi_chunks()
+ self.test_init()
+
+ def test_parser(self):
+ _res = self.sc.parser(six.binary_type(self.buf))
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+ # to calculate the lengths of parameters.
+ self.sc.serialize(None, None)
+
+ eq_(self.src_port, res.src_port)
+ eq_(self.dst_port, res.dst_port)
+ eq_(self.vtag, res.vtag)
+ eq_(self.csum, res.csum)
+ eq_(str(self.chunks), str(res.chunks))
+
+ def test_parser_with_data(self):
+ self.setUp_with_data()
+ self.test_parser()
+
+ def test_parser_with_init(self):
+ self.setUp_with_init()
+ self.test_parser()
+
+ def test_parser_with_init_ack(self):
+ self.setUp_with_init_ack()
+ self.test_parser()
+
+ def test_parser_with_sack(self):
+ self.setUp_with_sack()
+ self.test_parser()
+
+ def test_parser_with_heartbeat(self):
+ self.setUp_with_heartbeat()
+ self.test_parser()
+
+ def test_parser_with_heartbeat_ack(self):
+ self.setUp_with_heartbeat_ack()
+ self.test_parser()
+
+ def test_parser_with_abort(self):
+ self.setUp_with_abort()
+ self.test_parser()
+
+ def test_parser_with_shutdown(self):
+ self.setUp_with_shutdown()
+ self.test_parser()
+
+ def test_parser_with_shutdown_ack(self):
+ self.setUp_with_shutdown_ack()
+ self.test_parser()
+
+ def test_parser_with_error(self):
+ self.setUp_with_error()
+ self.test_parser()
+
+ def test_parser_with_cookie_echo(self):
+ self.setUp_with_cookie_echo()
+ self.test_parser()
+
+ def test_parser_with_cookie_ack(self):
+ self.setUp_with_cookie_ack()
+ self.test_parser()
+
+ def test_parser_with_ecn_echo(self):
+ self.setUp_with_ecn_echo()
+ self.test_parser()
+
+ def test_parser_with_cwr(self):
+ self.setUp_with_cwr()
+ self.test_parser()
+
+ def test_parser_with_shutdown_complete(self):
+ self.setUp_with_shutdown_complete()
+ self.test_parser()
+
+ def test_parser_with_multi_chunks(self):
+ self.setUp_with_multi_chunks()
+ self.test_parser()
+
+ def _test_serialize(self):
+ buf = self.sc.serialize(bytearray(), None)
+ res = struct.unpack_from(sctp.sctp._PACK_STR, buf)
+ eq_(self.src_port, res[0])
+ eq_(self.dst_port, res[1])
+ eq_(self.vtag, res[2])
+ # skip compare checksum
+ # eq_(self.csum, res[3])
+
+ return buf[sctp.sctp._MIN_LEN:]
+
+ def test_serialize(self):
+ self._test_serialize()
+
+ def test_serialize_with_data(self):
+ self.setUp_with_data()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_data._PACK_STR, buf)
+ eq_(sctp.chunk_data.chunk_type(), res[0])
+ flags = (
+ (self.unordered << 2) |
+ (self.begin << 1) |
+ (self.end << 0))
+ eq_(flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.tsn, res[3])
+ eq_(self.sid, res[4])
+ eq_(self.seq, res[5])
+ eq_(self.payload_id, res[6])
+ eq_(self.payload_data, buf[sctp.chunk_data._MIN_LEN:])
+
+ def test_serialize_with_init(self):
+ self.setUp_with_init()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_init._PACK_STR, buf)
+ eq_(sctp.chunk_init.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.init_tag, res[3])
+ eq_(self.a_rwnd, res[4])
+ eq_(self.os, res[5])
+ eq_(self.mis, res[6])
+ eq_(self.i_tsn, res[7])
+
+ buf = buf[sctp.chunk_init._MIN_LEN:]
+ res1 = struct.unpack_from(sctp.param_ipv4._PACK_STR, buf)
+ eq_(sctp.param_ipv4.param_type(), res1[0])
+ eq_(8, res1[1])
+ eq_('192.168.1.1', addrconv.ipv4.bin_to_text(
+ buf[sctp.param_ipv4._MIN_LEN:sctp.param_ipv4._MIN_LEN + 4]))
+
+ buf = buf[8:]
+ res2 = struct.unpack_from(sctp.param_ipv6._PACK_STR, buf)
+ eq_(sctp.param_ipv6.param_type(), res2[0])
+ eq_(20, res2[1])
+ eq_('fe80::647e:1aff:fec4:8284', addrconv.ipv6.bin_to_text(
+ buf[sctp.param_ipv6._MIN_LEN:sctp.param_ipv6._MIN_LEN + 16]))
+
+ buf = buf[20:]
+ res3 = struct.unpack_from(sctp.param_cookie_preserve._PACK_STR,
+ buf)
+ eq_(sctp.param_cookie_preserve.param_type(), res3[0])
+ eq_(8, res3[1])
+ eq_(5000, res3[2])
+
+ buf = buf[8:]
+ res4 = struct.unpack_from(sctp.param_ecn._PACK_STR, buf)
+ eq_(sctp.param_ecn.param_type(), res4[0])
+ eq_(4, res4[1])
+
+ buf = buf[4:]
+ res5 = struct.unpack_from(sctp.param_host_addr._PACK_STR, buf)
+ eq_(sctp.param_host_addr.param_type(), res5[0])
+ eq_(14, res5[1])
+ eq_(b'test host\x00',
+ buf[sctp.param_host_addr._MIN_LEN:
+ sctp.param_host_addr._MIN_LEN + 10])
+
+ buf = buf[16:]
+ res6 = struct.unpack_from(sctp.param_supported_addr._PACK_STR, buf)
+ res6 = list(res6)
+ eq_(sctp.param_supported_addr.param_type(), res6[0])
+ eq_(14, res6[1])
+ buf = buf[sctp.param_supported_addr._MIN_LEN:]
+ offset = 0
+ tmplist = []
+ while offset < len(buf):
+ (tmp, ) = struct.unpack_from('!H', buf, offset)
+ tmplist.append(tmp)
+ offset += struct.calcsize('!H')
+ res6.extend(tmplist)
+ eq_(sctp.PTYPE_IPV4, res6[2])
+ eq_(sctp.PTYPE_IPV6, res6[3])
+ eq_(sctp.PTYPE_COOKIE_PRESERVE, res6[4])
+ eq_(sctp.PTYPE_ECN, res6[5])
+ eq_(sctp.PTYPE_HOST_ADDR, res6[6])
+
+ def test_serialize_with_init_ack(self):
+ self.setUp_with_init_ack()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_init_ack._PACK_STR, buf)
+ eq_(sctp.chunk_init_ack.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.init_tag, res[3])
+ eq_(self.a_rwnd, res[4])
+ eq_(self.os, res[5])
+ eq_(self.mis, res[6])
+ eq_(self.i_tsn, res[7])
+
+ buf = buf[sctp.chunk_init_ack._MIN_LEN:]
+ res1 = struct.unpack_from(sctp.param_state_cookie._PACK_STR, buf)
+ eq_(sctp.param_state_cookie.param_type(), res1[0])
+ eq_(7, res1[1])
+ eq_(b'\x01\x02\x03',
+ buf[sctp.param_state_cookie._MIN_LEN:
+ sctp.param_state_cookie._MIN_LEN + 3])
+
+ buf = buf[8:]
+ res2 = struct.unpack_from(sctp.param_ipv4._PACK_STR, buf)
+ eq_(sctp.param_ipv4.param_type(), res2[0])
+ eq_(8, res2[1])
+ eq_('192.168.1.1', addrconv.ipv4.bin_to_text(
+ buf[sctp.param_ipv4._MIN_LEN:sctp.param_ipv4._MIN_LEN + 4]))
+
+ buf = buf[8:]
+ res3 = struct.unpack_from(sctp.param_ipv6._PACK_STR, buf)
+ eq_(sctp.param_ipv6.param_type(), res3[0])
+ eq_(20, res3[1])
+ eq_('fe80::647e:1aff:fec4:8284', addrconv.ipv6.bin_to_text(
+ buf[sctp.param_ipv6._MIN_LEN:sctp.param_ipv6._MIN_LEN + 16]))
+
+ buf = buf[20:]
+ res4 = struct.unpack_from(
+ sctp.param_unrecognized_param._PACK_STR, buf)
+ eq_(sctp.param_unrecognized_param.param_type(), res4[0])
+ eq_(8, res4[1])
+ eq_(b'\xff\xff\x00\x04',
+ buf[sctp.param_unrecognized_param._MIN_LEN:
+ sctp.param_unrecognized_param._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res5 = struct.unpack_from(sctp.param_ecn._PACK_STR, buf)
+ eq_(sctp.param_ecn.param_type(), res5[0])
+ eq_(4, res5[1])
+
+ buf = buf[4:]
+ res6 = struct.unpack_from(sctp.param_host_addr._PACK_STR, buf)
+ eq_(sctp.param_host_addr.param_type(), res6[0])
+ eq_(14, res6[1])
+ eq_(b'test host\x00',
+ buf[sctp.param_host_addr._MIN_LEN:
+ sctp.param_host_addr._MIN_LEN + 10])
+
+ def test_serialize_with_sack(self):
+ self.setUp_with_sack()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_sack._PACK_STR, buf)
+ eq_(sctp.chunk_sack.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.tsn_ack, res[3])
+ eq_(self.a_rwnd, res[4])
+ eq_(self.gapack_num, res[5])
+ eq_(self.duptsn_num, res[6])
+
+ buf = buf[sctp.chunk_sack._MIN_LEN:]
+ gapacks = []
+ for _ in range(self.gapack_num):
+ (gap_s, gap_e) = struct.unpack_from(
+ sctp.chunk_sack._GAPACK_STR, buf)
+ one = [gap_s, gap_e]
+ gapacks.append(one)
+ buf = buf[sctp.chunk_sack._GAPACK_LEN:]
+ duptsns = []
+ for _ in range(self.duptsn_num):
+ (duptsn, ) = struct.unpack_from(
+ sctp.chunk_sack._DUPTSN_STR, buf)
+ duptsns.append(duptsn)
+ buf = buf[sctp.chunk_sack._DUPTSN_LEN:]
+ eq_(self.gapacks, gapacks)
+ eq_(self.duptsns, duptsns)
+
+ def test_serialize_with_heartbeat(self):
+ self.setUp_with_heartbeat()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_heartbeat._PACK_STR, buf)
+ eq_(sctp.chunk_heartbeat.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+
+ buf = buf[sctp.chunk_heartbeat._MIN_LEN:]
+ res1 = struct.unpack_from(sctp.param_heartbeat._PACK_STR, buf)
+ eq_(sctp.param_heartbeat.param_type(), res1[0])
+ eq_(8, res1[1])
+ eq_(b'\x01\x02\x03\x04',
+ buf[sctp.param_heartbeat._MIN_LEN:
+ sctp.param_heartbeat._MIN_LEN + 4])
+
+ def test_serialize_with_heartbeat_ack(self):
+ self.setUp_with_heartbeat_ack()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_heartbeat_ack._PACK_STR, buf)
+ eq_(sctp.chunk_heartbeat_ack.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+
+ buf = buf[sctp.chunk_heartbeat_ack._MIN_LEN:]
+ res1 = struct.unpack_from(sctp.param_heartbeat._PACK_STR, buf)
+ eq_(sctp.param_heartbeat.param_type(), res1[0])
+ eq_(12, res1[1])
+ eq_(b'\xff\xee\xdd\xcc\xbb\xaa\x99\x88',
+ buf[sctp.param_heartbeat._MIN_LEN:
+ sctp.param_heartbeat._MIN_LEN + 8])
+
+ def test_serialize_with_abort(self):
+ self.setUp_with_abort()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_abort._PACK_STR, buf)
+ eq_(sctp.chunk_abort.chunk_type(), res[0])
+ flags = self.tflag << 0
+ eq_(flags, res[1])
+ eq_(self.length, res[2])
+
+ buf = buf[sctp.chunk_abort._MIN_LEN:]
+ res1 = struct.unpack_from(sctp.cause_invalid_stream_id._PACK_STR, buf)
+ eq_(sctp.cause_invalid_stream_id.cause_code(), res1[0])
+ eq_(8, res1[1])
+ eq_(4096, res1[2])
+
+ buf = buf[8:]
+ res2 = struct.unpack_from(sctp.cause_missing_param._PACK_STR, buf)
+ eq_(sctp.cause_missing_param.cause_code(), res2[0])
+ eq_(16, res2[1])
+ eq_(4, res2[2])
+ types = []
+ for count in range(4):
+ (tmp, ) = struct.unpack_from(
+ '!H', buf, sctp.cause_missing_param._MIN_LEN + 2 * count)
+ types.append(tmp)
+ eq_(str([sctp.PTYPE_IPV4, sctp.PTYPE_IPV6,
+ sctp.PTYPE_COOKIE_PRESERVE, sctp.PTYPE_HOST_ADDR]),
+ str(types))
+
+ buf = buf[16:]
+ res3 = struct.unpack_from(sctp.cause_stale_cookie._PACK_STR, buf)
+ eq_(sctp.cause_stale_cookie.cause_code(), res3[0])
+ eq_(8, res3[1])
+ eq_(b'\x00\x00\x13\x88',
+ buf[sctp.cause_stale_cookie._MIN_LEN:
+ sctp.cause_stale_cookie._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res4 = struct.unpack_from(sctp.cause_out_of_resource._PACK_STR, buf)
+ eq_(sctp.cause_out_of_resource.cause_code(), res4[0])
+ eq_(4, res4[1])
+
+ buf = buf[4:]
+ res5 = struct.unpack_from(
+ sctp.cause_unresolvable_addr._PACK_STR, buf)
+ eq_(sctp.cause_unresolvable_addr.cause_code(), res5[0])
+ eq_(20, res5[1])
+ eq_(b'\x00\x0b\x00\x0e\x74\x65\x73\x74' +
+ b'\x20\x68\x6f\x73\x74\x00\x00\x00',
+ buf[sctp.cause_unresolvable_addr._MIN_LEN:
+ sctp.cause_unresolvable_addr._MIN_LEN + 16])
+
+ buf = buf[20:]
+ res6 = struct.unpack_from(
+ sctp.cause_unrecognized_chunk._PACK_STR, buf)
+ eq_(sctp.cause_unrecognized_chunk.cause_code(), res6[0])
+ eq_(8, res6[1])
+ eq_(b'\xff\x00\x00\x04',
+ buf[sctp.cause_unrecognized_chunk._MIN_LEN:
+ sctp.cause_unrecognized_chunk._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res7 = struct.unpack_from(sctp.cause_invalid_param._PACK_STR, buf)
+ eq_(sctp.cause_invalid_param.cause_code(), res7[0])
+ eq_(4, res7[1])
+
+ buf = buf[4:]
+ res8 = struct.unpack_from(
+ sctp.cause_unrecognized_param._PACK_STR, buf)
+ eq_(sctp.cause_unrecognized_param.cause_code(), res8[0])
+ eq_(8, res8[1])
+ eq_(b'\xff\xff\x00\x04',
+ buf[sctp.cause_unrecognized_param._MIN_LEN:
+ sctp.cause_unrecognized_param._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res9 = struct.unpack_from(sctp.cause_no_userdata._PACK_STR, buf)
+ eq_(sctp.cause_no_userdata.cause_code(), res9[0])
+ eq_(8, res9[1])
+ eq_(b'\x00\x01\xe2\x40',
+ buf[sctp.cause_no_userdata._MIN_LEN:
+ sctp.cause_no_userdata._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res10 = struct.unpack_from(
+ sctp.cause_cookie_while_shutdown._PACK_STR, buf)
+ eq_(sctp.cause_cookie_while_shutdown.cause_code(), res10[0])
+ eq_(4, res10[1])
+
+ buf = buf[4:]
+ res11 = struct.unpack_from(
+ sctp.cause_restart_with_new_addr._PACK_STR, buf)
+ eq_(sctp.cause_restart_with_new_addr.cause_code(), res11[0])
+ eq_(12, res11[1])
+ eq_(b'\x00\x05\x00\x08\xc0\xa8\x01\x01',
+ buf[sctp.cause_restart_with_new_addr._MIN_LEN:
+ sctp.cause_restart_with_new_addr._MIN_LEN + 8])
+
+ buf = buf[12:]
+ res12 = struct.unpack_from(
+ sctp.cause_user_initiated_abort._PACK_STR, buf)
+ eq_(sctp.cause_user_initiated_abort.cause_code(), res12[0])
+ eq_(19, res12[1])
+ eq_(b'Key Interrupt.\x00',
+ buf[sctp.cause_user_initiated_abort._MIN_LEN:
+ sctp.cause_user_initiated_abort._MIN_LEN + 15])
+
+ buf = buf[20:]
+ res13 = struct.unpack_from(
+ sctp.cause_protocol_violation._PACK_STR, buf)
+ eq_(sctp.cause_protocol_violation.cause_code(), res13[0])
+ eq_(20, res13[1])
+ eq_(b'Unknown reason.\x00',
+ buf[sctp.cause_protocol_violation._MIN_LEN:
+ sctp.cause_protocol_violation._MIN_LEN + 16])
+
+ def test_serialize_with_shutdown(self):
+ self.setUp_with_shutdown()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_shutdown._PACK_STR, buf)
+ eq_(sctp.chunk_shutdown.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.tsn_ack, res[3])
+
+ def test_serialize_with_shutdown_ack(self):
+ self.setUp_with_shutdown_ack()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_shutdown_ack._PACK_STR, buf)
+ eq_(sctp.chunk_shutdown_ack.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+
+ def test_serialize_with_error(self):
+ self.setUp_with_error()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_error._PACK_STR, buf)
+ eq_(sctp.chunk_error.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+
+ buf = buf[sctp.chunk_error._MIN_LEN:]
+ res1 = struct.unpack_from(sctp.cause_invalid_stream_id._PACK_STR, buf)
+ eq_(sctp.cause_invalid_stream_id.cause_code(), res1[0])
+ eq_(8, res1[1])
+ eq_(4096, res1[2])
+
+ buf = buf[8:]
+ res2 = struct.unpack_from(sctp.cause_missing_param._PACK_STR, buf)
+ eq_(sctp.cause_missing_param.cause_code(), res2[0])
+ eq_(16, res2[1])
+ eq_(4, res2[2])
+ types = []
+ for count in range(4):
+ (tmp, ) = struct.unpack_from(
+ '!H', buf, sctp.cause_missing_param._MIN_LEN + 2 * count)
+ types.append(tmp)
+ eq_(str([sctp.PTYPE_IPV4, sctp.PTYPE_IPV6,
+ sctp.PTYPE_COOKIE_PRESERVE, sctp.PTYPE_HOST_ADDR]),
+ str(types))
+
+ buf = buf[16:]
+ res3 = struct.unpack_from(sctp.cause_stale_cookie._PACK_STR, buf)
+ eq_(sctp.cause_stale_cookie.cause_code(), res3[0])
+ eq_(8, res3[1])
+ eq_(b'\x00\x00\x13\x88',
+ buf[sctp.cause_stale_cookie._MIN_LEN:
+ sctp.cause_stale_cookie._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res4 = struct.unpack_from(sctp.cause_out_of_resource._PACK_STR, buf)
+ eq_(sctp.cause_out_of_resource.cause_code(), res4[0])
+ eq_(4, res4[1])
+
+ buf = buf[4:]
+ res5 = struct.unpack_from(
+ sctp.cause_unresolvable_addr._PACK_STR, buf)
+ eq_(sctp.cause_unresolvable_addr.cause_code(), res5[0])
+ eq_(20, res5[1])
+ eq_(b'\x00\x0b\x00\x0e\x74\x65\x73\x74' +
+ b'\x20\x68\x6f\x73\x74\x00\x00\x00',
+ buf[sctp.cause_unresolvable_addr._MIN_LEN:
+ sctp.cause_unresolvable_addr._MIN_LEN + 16])
+
+ buf = buf[20:]
+ res6 = struct.unpack_from(
+ sctp.cause_unrecognized_chunk._PACK_STR, buf)
+ eq_(sctp.cause_unrecognized_chunk.cause_code(), res6[0])
+ eq_(8, res6[1])
+ eq_(b'\xff\x00\x00\x04',
+ buf[sctp.cause_unrecognized_chunk._MIN_LEN:
+ sctp.cause_unrecognized_chunk._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res7 = struct.unpack_from(sctp.cause_invalid_param._PACK_STR, buf)
+ eq_(sctp.cause_invalid_param.cause_code(), res7[0])
+ eq_(4, res7[1])
+
+ buf = buf[4:]
+ res8 = struct.unpack_from(
+ sctp.cause_unrecognized_param._PACK_STR, buf)
+ eq_(sctp.cause_unrecognized_param.cause_code(), res8[0])
+ eq_(8, res8[1])
+ eq_(b'\xff\xff\x00\x04',
+ buf[sctp.cause_unrecognized_param._MIN_LEN:
+ sctp.cause_unrecognized_param._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res9 = struct.unpack_from(sctp.cause_no_userdata._PACK_STR, buf)
+ eq_(sctp.cause_no_userdata.cause_code(), res9[0])
+ eq_(8, res9[1])
+ eq_(b'\x00\x01\xe2\x40',
+ buf[sctp.cause_no_userdata._MIN_LEN:
+ sctp.cause_no_userdata._MIN_LEN + 4])
+
+ buf = buf[8:]
+ res10 = struct.unpack_from(
+ sctp.cause_cookie_while_shutdown._PACK_STR, buf)
+ eq_(sctp.cause_cookie_while_shutdown.cause_code(), res10[0])
+ eq_(4, res10[1])
+
+ buf = buf[4:]
+ res11 = struct.unpack_from(
+ sctp.cause_restart_with_new_addr._PACK_STR, buf)
+ eq_(sctp.cause_restart_with_new_addr.cause_code(), res11[0])
+ eq_(12, res11[1])
+ eq_(b'\x00\x05\x00\x08\xc0\xa8\x01\x01',
+ buf[sctp.cause_restart_with_new_addr._MIN_LEN:
+ sctp.cause_restart_with_new_addr._MIN_LEN + 8])
+
+ buf = buf[12:]
+ res12 = struct.unpack_from(
+ sctp.cause_user_initiated_abort._PACK_STR, buf)
+ eq_(sctp.cause_user_initiated_abort.cause_code(), res12[0])
+ eq_(19, res12[1])
+ eq_(b'Key Interrupt.\x00',
+ buf[sctp.cause_user_initiated_abort._MIN_LEN:
+ sctp.cause_user_initiated_abort._MIN_LEN + 15])
+
+ buf = buf[20:]
+ res13 = struct.unpack_from(
+ sctp.cause_protocol_violation._PACK_STR, buf)
+ eq_(sctp.cause_protocol_violation.cause_code(), res13[0])
+ eq_(20, res13[1])
+ eq_(b'Unknown reason.\x00',
+ buf[sctp.cause_protocol_violation._MIN_LEN:
+ sctp.cause_protocol_violation._MIN_LEN + 16])
+
+ def test_serialize_with_cookie_echo(self):
+ self.setUp_with_cookie_echo()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_cookie_echo._PACK_STR, buf)
+ eq_(sctp.chunk_cookie_echo.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.cookie,
+ buf[sctp.chunk_cookie_echo._MIN_LEN:
+ sctp.chunk_cookie_echo._MIN_LEN + 4])
+
+ def test_serialize_with_cookie_ack(self):
+ self.setUp_with_cookie_ack()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_cookie_ack._PACK_STR, buf)
+ eq_(sctp.chunk_cookie_ack.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+
+ def test_serialize_with_ecn_echo(self):
+ self.setUp_with_ecn_echo()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_ecn_echo._PACK_STR, buf)
+ eq_(sctp.chunk_ecn_echo.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.low_tsn, res[3])
+
+ def test_serialize_with_cwr(self):
+ self.setUp_with_cwr()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_cwr._PACK_STR, buf)
+ eq_(sctp.chunk_cwr.chunk_type(), res[0])
+ eq_(self.flags, res[1])
+ eq_(self.length, res[2])
+ eq_(self.low_tsn, res[3])
+
+ def test_serialize_with_shutdown_complete(self):
+ self.setUp_with_shutdown_complete()
+ buf = self._test_serialize()
+ res = struct.unpack_from(
+ sctp.chunk_shutdown_complete._PACK_STR, buf)
+ eq_(sctp.chunk_shutdown_complete.chunk_type(), res[0])
+ flags = self.tflag << 0
+ eq_(flags, res[1])
+ eq_(self.length, res[2])
+
+ def test_serialize_with_multi_chunks(self):
+ self.setUp_with_multi_chunks()
+ buf = self._test_serialize()
+ res = struct.unpack_from(sctp.chunk_sack._PACK_STR, buf)
+ eq_(sctp.chunk_sack.chunk_type(), res[0])
+ eq_(self.s_flags, res[1])
+ eq_(self.s_length, res[2])
+ eq_(self.s_tsn_ack, res[3])
+ eq_(self.s_a_rwnd, res[4])
+ eq_(self.s_gapack_num, res[5])
+ eq_(self.s_duptsn_num, res[6])
+
+ buf = buf[self.s_length:]
+ res = struct.unpack_from(sctp.chunk_data._PACK_STR, buf)
+ eq_(sctp.chunk_data.chunk_type(), res[0])
+ d1_flags = (
+ (self.d1_unordered << 2) |
+ (self.d1_begin << 1) |
+ (self.d1_end << 0))
+ eq_(d1_flags, res[1])
+ eq_(self.d1_length, res[2])
+ eq_(self.d1_tsn, res[3])
+ eq_(self.d1_sid, res[4])
+ eq_(self.d1_seq, res[5])
+ eq_(self.d1_payload_id, res[6])
+ eq_(self.d1_payload_data,
+ buf[sctp.chunk_data._MIN_LEN:
+ sctp.chunk_data._MIN_LEN + 10])
+
+ buf = buf[self.d1_length:]
+ res = struct.unpack_from(sctp.chunk_data._PACK_STR, buf)
+ eq_(sctp.chunk_data.chunk_type(), res[0])
+ d2_flags = (
+ (self.d2_unordered << 2) |
+ (self.d2_begin << 1) |
+ (self.d2_end << 0))
+ eq_(d2_flags, res[1])
+ eq_(self.d2_length, res[2])
+ eq_(self.d2_tsn, res[3])
+ eq_(self.d2_sid, res[4])
+ eq_(self.d2_seq, res[5])
+ eq_(self.d2_payload_id, res[6])
+ eq_(self.d2_payload_data,
+ buf[sctp.chunk_data._MIN_LEN:
+ sctp.chunk_data._MIN_LEN + 10])
+
+ def test_build_sctp(self):
+ eth = ethernet.ethernet('00:aa:aa:aa:aa:aa', '00:bb:bb:bb:bb:bb',
+ ether.ETH_TYPE_IP)
+ ip4 = ipv4.ipv4(4, 5, 16, 0, 0, 2, 0, 64, inet.IPPROTO_SCTP, 0,
+ '192.168.1.1', '10.144.1.1')
+ pkt = eth / ip4 / self.sc
+
+ eth = pkt.get_protocol(ethernet.ethernet)
+ ok_(eth)
+ eq_(eth.ethertype, ether.ETH_TYPE_IP)
+
+ ip4 = pkt.get_protocol(ipv4.ipv4)
+ ok_(ip4)
+ eq_(ip4.proto, inet.IPPROTO_SCTP)
+
+ sc = pkt.get_protocol(sctp.sctp)
+ ok_(sc)
+ eq_(sc, self.sc)
+
+ def test_build_sctp_with_data(self):
+ self.setUp_with_data()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_init(self):
+ self.setUp_with_init()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_init_ack(self):
+ self.setUp_with_init_ack()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_sack(self):
+ self.setUp_with_sack()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_heartbeat(self):
+ self.setUp_with_heartbeat()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_heartbeat_ack(self):
+ self.setUp_with_heartbeat_ack()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_abort(self):
+ self.setUp_with_abort()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_shutdown(self):
+ self.setUp_with_shutdown()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_shutdown_ack(self):
+ self.setUp_with_shutdown_ack()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_error(self):
+ self.setUp_with_error()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_cookie_echo(self):
+ self.setUp_with_cookie_echo()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_cookie_ack(self):
+ self.setUp_with_cookie_ack()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_ecn_echo(self):
+ self.setUp_with_ecn_echo()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_cwr(self):
+ self.setUp_with_cwr()
+ self.test_build_sctp()
+
+ def test_build_sctp_with_shutdown_complete(self):
+ self.setUp_with_shutdown_complete()
+ self.test_build_sctp()
+
+ def tset_build_sctp_with_multi_chunks(self):
+ self.setUp_with_multi_chunks()
+ self.test_build_sctp()
+
+ def test_to_string(self):
+ sctp_values = {'src_port': self.src_port,
+ 'dst_port': self.dst_port,
+ 'vtag': self.vtag,
+ 'csum': self.csum,
+ 'chunks': self.chunks}
+ _sctp_str = ','.join(['%s=%s' % (k, sctp_values[k])
+ for k, _ in inspect.getmembers(self.sc)
+ if k in sctp_values])
+ sctp_str = '%s(%s)' % (sctp.sctp.__name__, _sctp_str)
+
+ eq_(str(self.sc), sctp_str)
+ eq_(repr(self.sc), sctp_str)
+
+ def test_to_string_with_data(self):
+ self.setUp_with_data()
+ self.test_to_string()
+
+ def test_to_string_with_init(self):
+ self.setUp_with_init()
+ self.test_to_string()
+
+ def test_to_string_with_init_ack(self):
+ self.setUp_with_init_ack()
+ self.test_to_string()
+
+ def test_to_string_with_sack(self):
+ self.setUp_with_sack()
+ self.test_to_string()
+
+ def test_to_string_with_heartbeat(self):
+ self.setUp_with_heartbeat()
+ self.test_to_string()
+
+ def test_to_string_with_heartbeat_ack(self):
+ self.setUp_with_heartbeat_ack()
+ self.test_to_string()
+
+ def test_to_string_with_abort(self):
+ self.setUp_with_abort()
+ self.test_to_string()
+
+ def test_to_string_with_shutdown(self):
+ self.setUp_with_shutdown()
+ self.test_to_string()
+
+ def test_to_string_with_shutdown_ack(self):
+ self.setUp_with_shutdown_ack()
+ self.test_to_string()
+
+ def test_to_string_with_error(self):
+ self.setUp_with_error()
+ self.test_to_string()
+
+ def test_to_string_with_cookie_echo(self):
+ self.setUp_with_cookie_echo()
+ self.test_to_string()
+
+ def test_to_string_with_cookie_ack(self):
+ self.setUp_with_cookie_ack()
+ self.test_to_string()
+
+ def test_to_string_with_ecn_echo(self):
+ self.setUp_with_ecn_echo()
+ self.test_to_string()
+
+ def test_to_string_with_cwr(self):
+ self.setUp_with_cwr()
+ self.test_to_string()
+
+ def test_to_string_with_shutdown_complete(self):
+ self.setUp_with_shutdown_complete()
+ self.test_to_string()
+
+ def test_to_string_with_multi_chunks(self):
+ self.setUp_with_multi_chunks()
+ self.test_to_string()
+
+ def test_json(self):
+ jsondict = self.sc.to_jsondict()
+ sc = sctp.sctp.from_jsondict(jsondict['sctp'])
+ eq_(str(self.sc), str(sc))
+
+ def test_json_with_data(self):
+ self.setUp_with_data()
+ self.test_json()
+
+ def test_json_with_init(self):
+ self.setUp_with_init()
+ self.test_json()
+
+ def test_json_with_init_ack(self):
+ self.setUp_with_init_ack()
+ self.test_json()
+
+ def test_json_with_sack(self):
+ self.setUp_with_sack()
+ self.test_json()
+
+ def test_json_with_heartbeat(self):
+ self.setUp_with_heartbeat()
+ self.test_json()
+
+ def test_json_with_heartbeat_ack(self):
+ self.setUp_with_heartbeat_ack()
+ self.test_json()
+
+ def test_json_with_abort(self):
+ self.setUp_with_abort()
+ self.test_json()
+
+ def test_json_with_shutdown(self):
+ self.setUp_with_shutdown()
+ self.test_json()
+
+ def test_json_with_shutdown_ack(self):
+ self.setUp_with_shutdown_ack()
+ self.test_json()
+
+ def test_json_with_error(self):
+ self.setUp_with_error()
+ self.test_json()
+
+ def test_json_with_cookie_echo(self):
+ self.setUp_with_cookie_echo()
+ self.test_json()
+
+ def test_json_with_cookie_ack(self):
+ self.setUp_with_cookie_ack()
+ self.test_json()
+
+ def test_json_with_ecn_echo(self):
+ self.setUp_with_ecn_echo()
+ self.test_json()
+
+ def test_json_with_cwr(self):
+ self.setUp_with_cwr()
+ self.test_json()
+
+ def test_json_with_shutdown_complete(self):
+ self.setUp_with_shutdown_complete()
+ self.test_json()
+
+ def test_json_with_multi_chunks(self):
+ self.setUp_with_multi_chunks()
+ self.test_json()
diff --git a/tests/unit/packet/test_slow.py b/tests/unit/packet/test_slow.py
new file mode 100644
index 00000000..9e077fd2
--- /dev/null
+++ b/tests/unit/packet/test_slow.py
@@ -0,0 +1,1104 @@
+# Copyright (C) 2013 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 copy
+import logging
+from struct import pack, unpack_from
+import unittest
+
+from nose.tools import ok_, eq_, raises
+from ryu.ofproto import ether
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.packet import Packet
+from ryu.lib import addrconv
+from ryu.lib.packet.slow import slow, lacp
+from ryu.lib.packet.slow import SLOW_PROTOCOL_MULTICAST
+from ryu.lib.packet.slow import SLOW_SUBTYPE_LACP
+from ryu.lib.packet.slow import SLOW_SUBTYPE_MARKER
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_slow(unittest.TestCase):
+ """ Test case for Slow Protocol
+ """
+ def setUp(self):
+ self.subtype = SLOW_SUBTYPE_LACP
+ self.version = lacp.LACP_VERSION_NUMBER
+ self.actor_tag = lacp.LACP_TLV_TYPE_ACTOR
+ self.actor_length = 20
+ self.actor_system_priority = 65534
+ self.actor_system = '00:07:0d:af:f4:54'
+ self.actor_key = 1
+ self.actor_port_priority = 65535
+ self.actor_port = 1
+ self.actor_state_activity = lacp.LACP_STATE_ACTIVE
+ self.actor_state_timeout = lacp.LACP_STATE_LONG_TIMEOUT
+ self.actor_state_aggregation = lacp.LACP_STATE_AGGREGATEABLE
+ self.actor_state_synchronization = lacp.LACP_STATE_IN_SYNC
+ self.actor_state_collecting = lacp.LACP_STATE_COLLECTING_ENABLED
+ self.actor_state_distributing = lacp.LACP_STATE_DISTRIBUTING_ENABLED
+ self.actor_state_defaulted = lacp.LACP_STATE_OPERATIONAL_PARTNER
+ self.actor_state_expired = lacp.LACP_STATE_EXPIRED
+ self.actor_state = (
+ (self.actor_state_activity << 0) |
+ (self.actor_state_timeout << 1) |
+ (self.actor_state_aggregation << 2) |
+ (self.actor_state_synchronization << 3) |
+ (self.actor_state_collecting << 4) |
+ (self.actor_state_distributing << 5) |
+ (self.actor_state_defaulted << 6) |
+ (self.actor_state_expired << 7))
+ self.partner_tag = lacp.LACP_TLV_TYPE_PARTNER
+ self.partner_length = 20
+ self.partner_system_priority = 0
+ self.partner_system = '00:00:00:00:00:00'
+ self.partner_key = 0
+ self.partner_port_priority = 0
+ self.partner_port = 0
+ self.partner_state_activity = 0
+ self.partner_state_timeout = lacp.LACP_STATE_SHORT_TIMEOUT
+ self.partner_state_aggregation = 0
+ self.partner_state_synchronization = 0
+ self.partner_state_collecting = 0
+ self.partner_state_distributing = 0
+ self.partner_state_defaulted = 0
+ self.partner_state_expired = 0
+ self.partner_state = (
+ (self.partner_state_activity << 0) |
+ (self.partner_state_timeout << 1) |
+ (self.partner_state_aggregation << 2) |
+ (self.partner_state_synchronization << 3) |
+ (self.partner_state_collecting << 4) |
+ (self.partner_state_distributing << 5) |
+ (self.partner_state_defaulted << 6) |
+ (self.partner_state_expired << 7))
+ self.collector_tag = lacp.LACP_TLV_TYPE_COLLECTOR
+ self.collector_length = 16
+ self.collector_max_delay = 0
+ self.terminator_tag = lacp.LACP_TLV_TYPE_TERMINATOR
+ self.terminator_length = 0
+
+ self.head_fmt = lacp._HLEN_PACK_STR
+ self.head_len = lacp._HLEN_PACK_LEN
+ self.act_fmt = lacp._ACTPRT_INFO_PACK_STR
+ self.act_len = lacp._ACTPRT_INFO_PACK_LEN
+ self.prt_fmt = lacp._ACTPRT_INFO_PACK_STR
+ self.prt_len = lacp._ACTPRT_INFO_PACK_LEN
+ self.col_fmt = lacp._COL_INFO_PACK_STR
+ self.col_len = lacp._COL_INFO_PACK_LEN
+ self.trm_fmt = lacp._TRM_PACK_STR
+ self.trm_len = lacp._TRM_PACK_LEN
+ self.length = lacp._ALL_PACK_LEN
+
+ self.head_buf = pack(self.head_fmt,
+ self.subtype,
+ self.version)
+ self.act_buf = pack(self.act_fmt,
+ self.actor_tag,
+ self.actor_length,
+ self.actor_system_priority,
+ addrconv.mac.text_to_bin(self.actor_system),
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state)
+ self.prt_buf = pack(self.prt_fmt,
+ self.partner_tag,
+ self.partner_length,
+ self.partner_system_priority,
+ addrconv.mac.text_to_bin(self.partner_system),
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state)
+ self.col_buf = pack(self.col_fmt,
+ self.collector_tag,
+ self.collector_length,
+ self.collector_max_delay)
+ self.trm_buf = pack(self.trm_fmt,
+ self.terminator_tag,
+ self.terminator_length)
+
+ self.buf = self.head_buf + self.act_buf + self.prt_buf + \
+ self.col_buf + self.trm_buf
+
+ def tearDown(self):
+ pass
+
+ def test_parser(self):
+ slow.parser(self.buf)
+
+ def test_not_implemented_subtype(self):
+ not_implemented_buf = pack(
+ slow._PACK_STR, SLOW_SUBTYPE_MARKER) + self.buf[1:]
+ (instance, nexttype, last) = slow.parser(not_implemented_buf)
+ assert None == instance
+ assert None == nexttype
+ assert None != last
+
+ def test_invalid_subtype(self):
+ invalid_buf = b'\xff' + self.buf[1:]
+ (instance, nexttype, last) = slow.parser(invalid_buf)
+ assert None == instance
+ assert None == nexttype
+ assert None != last
+
+
+class Test_lacp(unittest.TestCase):
+ """ Test case for lacp
+ """
+
+ def setUp(self):
+ self.subtype = SLOW_SUBTYPE_LACP
+ self.version = lacp.LACP_VERSION_NUMBER
+ self.actor_tag = lacp.LACP_TLV_TYPE_ACTOR
+ self.actor_length = 20
+ self.actor_system_priority = 65534
+ self.actor_system = '00:07:0d:af:f4:54'
+ self.actor_key = 1
+ self.actor_port_priority = 65535
+ self.actor_port = 1
+ self.actor_state_activity = lacp.LACP_STATE_ACTIVE
+ self.actor_state_timeout = lacp.LACP_STATE_LONG_TIMEOUT
+ self.actor_state_aggregation = lacp.LACP_STATE_AGGREGATEABLE
+ self.actor_state_synchronization = lacp.LACP_STATE_IN_SYNC
+ self.actor_state_collecting = lacp.LACP_STATE_COLLECTING_ENABLED
+ self.actor_state_distributing = lacp.LACP_STATE_DISTRIBUTING_ENABLED
+ self.actor_state_defaulted = lacp.LACP_STATE_OPERATIONAL_PARTNER
+ self.actor_state_expired = lacp.LACP_STATE_EXPIRED
+ self.actor_state = (
+ (self.actor_state_activity << 0) |
+ (self.actor_state_timeout << 1) |
+ (self.actor_state_aggregation << 2) |
+ (self.actor_state_synchronization << 3) |
+ (self.actor_state_collecting << 4) |
+ (self.actor_state_distributing << 5) |
+ (self.actor_state_defaulted << 6) |
+ (self.actor_state_expired << 7))
+ self.partner_tag = lacp.LACP_TLV_TYPE_PARTNER
+ self.partner_length = 20
+ self.partner_system_priority = 0
+ self.partner_system = '00:00:00:00:00:00'
+ self.partner_key = 0
+ self.partner_port_priority = 0
+ self.partner_port = 0
+ self.partner_state_activity = 0
+ self.partner_state_timeout = lacp.LACP_STATE_SHORT_TIMEOUT
+ self.partner_state_aggregation = 0
+ self.partner_state_synchronization = 0
+ self.partner_state_collecting = 0
+ self.partner_state_distributing = 0
+ self.partner_state_defaulted = 0
+ self.partner_state_expired = 0
+ self.partner_state = (
+ (self.partner_state_activity << 0) |
+ (self.partner_state_timeout << 1) |
+ (self.partner_state_aggregation << 2) |
+ (self.partner_state_synchronization << 3) |
+ (self.partner_state_collecting << 4) |
+ (self.partner_state_distributing << 5) |
+ (self.partner_state_defaulted << 6) |
+ (self.partner_state_expired << 7))
+ self.collector_tag = lacp.LACP_TLV_TYPE_COLLECTOR
+ self.collector_length = 16
+ self.collector_max_delay = 0
+ self.terminator_tag = lacp.LACP_TLV_TYPE_TERMINATOR
+ self.terminator_length = 0
+
+ self.head_fmt = lacp._HLEN_PACK_STR
+ self.head_len = lacp._HLEN_PACK_LEN
+ self.act_fmt = lacp._ACTPRT_INFO_PACK_STR
+ self.act_len = lacp._ACTPRT_INFO_PACK_LEN
+ self.prt_fmt = lacp._ACTPRT_INFO_PACK_STR
+ self.prt_len = lacp._ACTPRT_INFO_PACK_LEN
+ self.col_fmt = lacp._COL_INFO_PACK_STR
+ self.col_len = lacp._COL_INFO_PACK_LEN
+ self.trm_fmt = lacp._TRM_PACK_STR
+ self.trm_len = lacp._TRM_PACK_LEN
+ self.length = lacp._ALL_PACK_LEN
+
+ self.head_buf = pack(self.head_fmt,
+ self.subtype,
+ self.version)
+ self.act_buf = pack(self.act_fmt,
+ self.actor_tag,
+ self.actor_length,
+ self.actor_system_priority,
+ addrconv.mac.text_to_bin(self.actor_system),
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state)
+ self.prt_buf = pack(self.prt_fmt,
+ self.partner_tag,
+ self.partner_length,
+ self.partner_system_priority,
+ addrconv.mac.text_to_bin(self.partner_system),
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state)
+ self.col_buf = pack(self.col_fmt,
+ self.collector_tag,
+ self.collector_length,
+ self.collector_max_delay)
+ self.trm_buf = pack(self.trm_fmt,
+ self.terminator_tag,
+ self.terminator_length)
+
+ self.buf = self.head_buf + self.act_buf + self.prt_buf + \
+ self.col_buf + self.trm_buf
+
+ self.l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.subtype, self.l._subtype)
+ eq_(self.version, self.l.version)
+ eq_(self.actor_tag, self.l._actor_tag)
+ eq_(self.actor_length, self.l._actor_length)
+ eq_(self.actor_system_priority, self.l.actor_system_priority)
+ eq_(self.actor_system, self.l.actor_system)
+ eq_(self.actor_key, self.l.actor_key)
+ eq_(self.actor_port_priority, self.l.actor_port_priority)
+ eq_(self.actor_port, self.l.actor_port)
+ eq_(self.actor_state_activity, self.l.actor_state_activity)
+ eq_(self.actor_state_timeout, self.l.actor_state_timeout)
+ eq_(self.actor_state_aggregation,
+ self.l.actor_state_aggregation)
+ eq_(self.actor_state_synchronization,
+ self.l.actor_state_synchronization)
+ eq_(self.actor_state_collecting,
+ self.l.actor_state_collecting)
+ eq_(self.actor_state_distributing,
+ self.l.actor_state_distributing)
+ eq_(self.actor_state_defaulted, self.l.actor_state_defaulted)
+ eq_(self.actor_state_expired, self.l.actor_state_expired)
+ eq_(self.actor_state, self.l._actor_state)
+ eq_(self.partner_tag, self.l._partner_tag)
+ eq_(self.partner_length, self.l._partner_length)
+ eq_(self.partner_system_priority,
+ self.l.partner_system_priority)
+ eq_(self.partner_system, self.l.partner_system)
+ eq_(self.partner_key, self.l.partner_key)
+ eq_(self.partner_port_priority, self.l.partner_port_priority)
+ eq_(self.partner_port, self.l.partner_port)
+ eq_(self.partner_state_activity, self.l.partner_state_activity)
+ eq_(self.partner_state_timeout, self.l.partner_state_timeout)
+ eq_(self.partner_state_aggregation,
+ self.l.partner_state_aggregation)
+ eq_(self.partner_state_synchronization,
+ self.l.partner_state_synchronization)
+ eq_(self.partner_state_collecting,
+ self.l.partner_state_collecting)
+ eq_(self.partner_state_distributing,
+ self.l.partner_state_distributing)
+ eq_(self.partner_state_defaulted,
+ self.l.partner_state_defaulted)
+ eq_(self.partner_state_expired, self.l.partner_state_expired)
+ eq_(self.partner_state, self.l._partner_state)
+ eq_(self.collector_tag, self.l._collector_tag)
+ eq_(self.collector_length, self.l._collector_length)
+ eq_(self.collector_max_delay, self.l.collector_max_delay)
+ eq_(self.terminator_tag, self.l._terminator_tag)
+ eq_(self.terminator_length, self.l._terminator_length)
+
+ def test_parser(self):
+ _res = self.l.parser(self.buf)
+ if type(_res) is tuple:
+ res = _res[0]
+ else:
+ res = _res
+
+ eq_(res._subtype, self.subtype)
+ eq_(res.version, self.version)
+ eq_(res._actor_tag, self.actor_tag)
+ eq_(res._actor_length, self.actor_length)
+ eq_(res.actor_system_priority, self.actor_system_priority)
+ eq_(res.actor_system, self.actor_system)
+ eq_(res.actor_key, self.actor_key)
+ eq_(res.actor_port_priority, self.actor_port_priority)
+ eq_(res.actor_port, self.actor_port)
+ eq_(res.actor_state_activity, self.actor_state_activity)
+ eq_(res.actor_state_timeout, self.actor_state_timeout)
+ eq_(res.actor_state_aggregation, self.actor_state_aggregation)
+ eq_(res.actor_state_synchronization,
+ self.actor_state_synchronization)
+ eq_(res.actor_state_collecting, self.actor_state_collecting)
+ eq_(res.actor_state_distributing, self.actor_state_distributing)
+ eq_(res.actor_state_defaulted, self.actor_state_defaulted)
+ eq_(res.actor_state_expired, self.actor_state_expired)
+ eq_(res._actor_state, self.actor_state)
+ eq_(res._partner_tag, self.partner_tag)
+ eq_(res._partner_length, self.partner_length)
+ eq_(res.partner_system_priority, self.partner_system_priority)
+ eq_(res.partner_system, self.partner_system)
+ eq_(res.partner_key, self.partner_key)
+ eq_(res.partner_port_priority, self.partner_port_priority)
+ eq_(res.partner_port, self.partner_port)
+ eq_(res.partner_state_activity, self.partner_state_activity)
+ eq_(res.partner_state_timeout, self.partner_state_timeout)
+ eq_(res.partner_state_aggregation,
+ self.partner_state_aggregation)
+ eq_(res.partner_state_synchronization,
+ self.partner_state_synchronization)
+ eq_(res.partner_state_collecting, self.partner_state_collecting)
+ eq_(res.partner_state_distributing,
+ self.partner_state_distributing)
+ eq_(res.partner_state_defaulted, self.partner_state_defaulted)
+ eq_(res.partner_state_expired, self.partner_state_expired)
+ eq_(res._partner_state, self.partner_state)
+ eq_(res._collector_tag, self.collector_tag)
+ eq_(res._collector_length, self.collector_length)
+ eq_(res.collector_max_delay, self.collector_max_delay)
+ eq_(res._terminator_tag, self.terminator_tag)
+ eq_(res._terminator_length, self.terminator_length)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.l.serialize(data, prev)
+
+ offset = 0
+ head_res = unpack_from(self.head_fmt, buf, offset)
+ offset += self.head_len
+ act_res = unpack_from(self.act_fmt, buf, offset)
+ offset += self.act_len
+ prt_res = unpack_from(self.prt_fmt, buf, offset)
+ offset += self.prt_len
+ col_res = unpack_from(self.col_fmt, buf, offset)
+ offset += self.col_len
+ trm_res = unpack_from(self.trm_fmt, buf, offset)
+
+ eq_(head_res[0], self.subtype)
+ eq_(head_res[1], self.version)
+
+ eq_(act_res[0], self.actor_tag)
+ eq_(act_res[1], self.actor_length)
+ eq_(act_res[2], self.actor_system_priority)
+ eq_(act_res[3], addrconv.mac.text_to_bin(self.actor_system))
+ eq_(act_res[4], self.actor_key)
+ eq_(act_res[5], self.actor_port_priority)
+ eq_(act_res[6], self.actor_port)
+ eq_(act_res[7], self.actor_state)
+
+ eq_(prt_res[0], self.partner_tag)
+ eq_(prt_res[1], self.partner_length)
+ eq_(prt_res[2], self.partner_system_priority)
+ eq_(prt_res[3], addrconv.mac.text_to_bin(self.partner_system))
+ eq_(prt_res[4], self.partner_key)
+ eq_(prt_res[5], self.partner_port_priority)
+ eq_(prt_res[6], self.partner_port)
+ eq_(prt_res[7], self.partner_state)
+
+ eq_(col_res[0], self.collector_tag)
+ eq_(col_res[1], self.collector_length)
+ eq_(col_res[2], self.collector_max_delay)
+
+ eq_(trm_res[0], self.terminator_tag)
+ eq_(trm_res[1], self.terminator_length)
+
+ def _build_lacp(self):
+ ethertype = ether.ETH_TYPE_SLOW
+ dst = SLOW_PROTOCOL_MULTICAST
+ e = ethernet(dst, self.actor_system, ethertype)
+ p = Packet()
+
+ p.add_protocol(e)
+ p.add_protocol(self.l)
+ p.serialize()
+ return p
+
+ def test_build_lacp(self):
+ p = self._build_lacp()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_SLOW)
+
+ l = self.find_protocol(p, "lacp")
+ ok_(l)
+
+ eq_(l._subtype, self.subtype)
+ eq_(l.version, self.version)
+ eq_(l._actor_tag, self.actor_tag)
+ eq_(l._actor_length, self.actor_length)
+ eq_(l.actor_system_priority, self.actor_system_priority)
+ eq_(l.actor_system, self.actor_system)
+ eq_(l.actor_key, self.actor_key)
+ eq_(l.actor_port_priority, self.actor_port_priority)
+ eq_(l.actor_port, self.actor_port)
+ eq_(l.actor_state_activity, self.actor_state_activity)
+ eq_(l.actor_state_timeout, self.actor_state_timeout)
+ eq_(l.actor_state_aggregation, self.actor_state_aggregation)
+ eq_(l.actor_state_synchronization,
+ self.actor_state_synchronization)
+ eq_(l.actor_state_collecting, self.actor_state_collecting)
+ eq_(l.actor_state_distributing, self.actor_state_distributing)
+ eq_(l.actor_state_defaulted, self.actor_state_defaulted)
+ eq_(l.actor_state_expired, self.actor_state_expired)
+ eq_(l._actor_state, self.actor_state)
+ eq_(l._partner_tag, self.partner_tag)
+ eq_(l._partner_length, self.partner_length)
+ eq_(l.partner_system_priority, self.partner_system_priority)
+ eq_(l.partner_system, self.partner_system)
+ eq_(l.partner_key, self.partner_key)
+ eq_(l.partner_port_priority, self.partner_port_priority)
+ eq_(l.partner_port, self.partner_port)
+ eq_(l.partner_state_activity, self.partner_state_activity)
+ eq_(l.partner_state_timeout, self.partner_state_timeout)
+ eq_(l.partner_state_aggregation, self.partner_state_aggregation)
+ eq_(l.partner_state_synchronization,
+ self.partner_state_synchronization)
+ eq_(l.partner_state_collecting, self.partner_state_collecting)
+ eq_(l.partner_state_distributing,
+ self.partner_state_distributing)
+ eq_(l.partner_state_defaulted, self.partner_state_defaulted)
+ eq_(l.partner_state_expired, self.partner_state_expired)
+ eq_(l._partner_state, self.partner_state)
+ eq_(l._collector_tag, self.collector_tag)
+ eq_(l._collector_length, self.collector_length)
+ eq_(l.collector_max_delay, self.collector_max_delay)
+ eq_(l._terminator_tag, self.terminator_tag)
+ eq_(l._terminator_length, self.terminator_length)
+
+ @raises(Exception)
+ def test_malformed_lacp(self):
+ m_short_buf = self.buf[1:self.length]
+ slow.parser(m_short_buf)
+
+ @raises(Exception)
+ def test_invalid_subtype(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.subtype = 0xff
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_version(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.version = 0xff
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_actor_tag(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.actor_tag = 0x04
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_actor_length(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.actor_length = 50
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_partner_tag(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.partner_tag = 0x01
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_partner_length(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.partner_length = 0
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_collector_tag(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.collector_tag = 0x00
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_collector_length(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.collector_length = 20
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_terminator_tag(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.terminator_tag = 0x04
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_terminator_length(self):
+ invalid_lacv = copy.deepcopy(self.l)
+ invalid_lacv.terminator_length = self.trm_len
+ invalid_buf = invalid_lacv.serialize()
+ slow.parser(invalid_buf)
+
+ @raises(Exception)
+ def test_invalid_actor_state_activity(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ 2,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_timeout(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ 2,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_aggregation(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ 2,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_synchronization(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ 2,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_collecting(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ 2,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_distributing(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ 2,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_defaulted(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ 2,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_actor_state_expired(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ 2,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_activity(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ -1,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_timeout(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ -1,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_aggregation(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ -1,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_synchronization(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ -1,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_collecting(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ -1,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_distributing(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ -1,
+ self.partner_state_defaulted,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_defaulted(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ -1,
+ self.partner_state_expired,
+ self.collector_max_delay)
+ l.serialize()
+
+ @raises(Exception)
+ def test_invalid_partner_state_expired(self):
+ l = lacp(self.version,
+ self.actor_system_priority,
+ self.actor_system,
+ self.actor_key,
+ self.actor_port_priority,
+ self.actor_port,
+ self.actor_state_activity,
+ self.actor_state_timeout,
+ self.actor_state_aggregation,
+ self.actor_state_synchronization,
+ self.actor_state_collecting,
+ self.actor_state_distributing,
+ self.actor_state_defaulted,
+ self.actor_state_expired,
+ self.partner_system_priority,
+ self.partner_system,
+ self.partner_key,
+ self.partner_port_priority,
+ self.partner_port,
+ self.partner_state_activity,
+ self.partner_state_timeout,
+ self.partner_state_aggregation,
+ self.partner_state_synchronization,
+ self.partner_state_collecting,
+ self.partner_state_distributing,
+ self.partner_state_defaulted,
+ -1,
+ self.collector_max_delay)
+ l.serialize()
+
+ def test_json(self):
+ jsondict = self.l.to_jsondict()
+ l = lacp.from_jsondict(jsondict['lacp'])
+ eq_(str(self.l), str(l))
diff --git a/tests/unit/packet/test_tcp.py b/tests/unit/packet/test_tcp.py
new file mode 100644
index 00000000..7224df0e
--- /dev/null
+++ b/tests/unit/packet/test_tcp.py
@@ -0,0 +1,267 @@
+# Copyright (C) 2012-2015 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 unittest
+import logging
+import six
+import struct
+from struct import *
+from nose.tools import *
+from ryu.ofproto import inet
+from ryu.lib.packet import tcp
+from ryu.lib.packet.ipv4 import ipv4
+from ryu.lib.packet import packet_utils
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger('test_tcp')
+
+
+class Test_tcp(unittest.TestCase):
+ """ Test case for tcp
+ """
+ src_port = 6431
+ dst_port = 8080
+ seq = 5
+ ack = 1
+ offset = 6
+ bits = 0b101010
+ window_size = 2048
+ csum = 12345
+ urgent = 128
+ option = b'\x01\x02\x03\x04'
+
+ t = tcp.tcp(src_port, dst_port, seq, ack, offset, bits,
+ window_size, csum, urgent, option)
+
+ buf = pack(tcp.tcp._PACK_STR, src_port, dst_port, seq, ack,
+ offset << 4, bits, window_size, csum, urgent)
+ buf += option
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.src_port, self.t.src_port)
+ eq_(self.dst_port, self.t.dst_port)
+ eq_(self.seq, self.t.seq)
+ eq_(self.ack, self.t.ack)
+ eq_(self.offset, self.t.offset)
+ eq_(self.bits, self.t.bits)
+ eq_(self.window_size, self.t.window_size)
+ eq_(self.csum, self.t.csum)
+ eq_(self.urgent, self.t.urgent)
+ eq_(self.option, self.t.option)
+
+ def test_parser(self):
+ r1, r2, _ = self.t.parser(self.buf)
+
+ eq_(self.src_port, r1.src_port)
+ eq_(self.dst_port, r1.dst_port)
+ eq_(self.seq, r1.seq)
+ eq_(self.ack, r1.ack)
+ eq_(self.offset, r1.offset)
+ eq_(self.bits, r1.bits)
+ eq_(self.window_size, r1.window_size)
+ eq_(self.csum, r1.csum)
+ eq_(self.urgent, r1.urgent)
+ eq_(self.option, r1.option)
+ eq_(None, r2)
+
+ def test_serialize(self):
+ offset = 5
+ csum = 0
+
+ src_ip = '192.168.10.1'
+ dst_ip = '192.168.100.1'
+ prev = ipv4(4, 5, 0, 0, 0, 0, 0, 64,
+ inet.IPPROTO_TCP, 0, src_ip, dst_ip)
+
+ t = tcp.tcp(self.src_port, self.dst_port, self.seq, self.ack,
+ offset, self.bits, self.window_size, csum, self.urgent)
+ buf = t.serialize(bytearray(), prev)
+ res = struct.unpack(tcp.tcp._PACK_STR, six.binary_type(buf))
+
+ eq_(res[0], self.src_port)
+ eq_(res[1], self.dst_port)
+ eq_(res[2], self.seq)
+ eq_(res[3], self.ack)
+ eq_(res[4], offset << 4)
+ eq_(res[5], self.bits)
+ eq_(res[6], self.window_size)
+ eq_(res[8], self.urgent)
+
+ # test __len__
+ # offset indicates the number of 32 bit (= 4 bytes)
+ # words in the TCP Header.
+ # So, we compare len(tcp) with offset * 4, here.
+ eq_(offset * 4, len(t))
+
+ # checksum
+ ph = struct.pack('!4s4sBBH',
+ addrconv.ipv4.text_to_bin(src_ip),
+ addrconv.ipv4.text_to_bin(dst_ip), 0, 6, offset * 4)
+ d = ph + buf
+ s = packet_utils.checksum(d)
+ eq_(0, s)
+
+ def test_serialize_option(self):
+ # prepare test data
+ offset = 0
+ csum = 0
+ option = [
+ tcp.TCPOptionMaximumSegmentSize(max_seg_size=1460),
+ tcp.TCPOptionSACKPermitted(),
+ tcp.TCPOptionTimestamps(ts_val=287454020, ts_ecr=1432778632),
+ tcp.TCPOptionNoOperation(),
+ tcp.TCPOptionWindowScale(shift_cnt=9),
+ ]
+ option_buf = (
+ b'\x02\x04\x05\xb4'
+ b'\x04\x02'
+ b'\x08\x0a\x11\x22\x33\x44\x55\x66\x77\x88'
+ b'\x01'
+ b'\x03\x03\x09'
+ )
+ prev = ipv4(4, 5, 0, 0, 0, 0, 0, 64,
+ inet.IPPROTO_TCP, 0, '192.168.10.1', '192.168.100.1')
+
+ # test serializer
+ t = tcp.tcp(self.src_port, self.dst_port, self.seq, self.ack,
+ offset, self.bits, self.window_size, csum, self.urgent,
+ option)
+ buf = t.serialize(bytearray(), prev)
+ r_option_buf = buf[tcp.tcp._MIN_LEN:tcp.tcp._MIN_LEN + len(option_buf)]
+ eq_(option_buf, r_option_buf)
+
+ # test parser
+ (r_tcp, _, _) = tcp.tcp.parser(buf)
+ eq_(str(option), str(r_tcp.option))
+
+ @raises(Exception)
+ def test_malformed_tcp(self):
+ m_short_buf = self.buf[1:tcp.tcp._MIN_LEN]
+ tcp.tcp.parser(m_short_buf)
+
+ def test_default_args(self):
+ prev = ipv4(proto=inet.IPPROTO_TCP)
+ t = tcp.tcp()
+ buf = t.serialize(bytearray(), prev)
+ res = struct.unpack(tcp.tcp._PACK_STR, buf)
+
+ eq_(res[0], 1)
+ eq_(res[1], 1)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 5 << 4)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[8], 0)
+
+ # with option, without offset
+ t = tcp.tcp(option=[tcp.TCPOptionMaximumSegmentSize(1460)])
+ buf = t.serialize(bytearray(), prev)
+ res = struct.unpack(tcp.tcp._PACK_STR + '4s', buf)
+
+ eq_(res[0], 1)
+ eq_(res[1], 1)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 6 << 4)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[8], 0)
+ eq_(res[9], b'\x02\x04\x05\xb4')
+
+ # with option, with long offset
+ t = tcp.tcp(offset=7, option=[tcp.TCPOptionWindowScale(shift_cnt=9)])
+ buf = t.serialize(bytearray(), prev)
+ res = struct.unpack(tcp.tcp._PACK_STR + '8s', buf)
+
+ eq_(res[0], 1)
+ eq_(res[1], 1)
+ eq_(res[2], 0)
+ eq_(res[3], 0)
+ eq_(res[4], 7 << 4)
+ eq_(res[5], 0)
+ eq_(res[6], 0)
+ eq_(res[8], 0)
+ eq_(res[9], b'\x03\x03\x09\x00\x00\x00\x00\x00')
+
+ def test_json(self):
+ jsondict = self.t.to_jsondict()
+ t = tcp.tcp.from_jsondict(jsondict['tcp'])
+ eq_(str(self.t), str(t))
+
+
+class Test_TCPOption(unittest.TestCase):
+ # prepare test data
+ input_options = [
+ tcp.TCPOptionEndOfOptionList(),
+ tcp.TCPOptionNoOperation(),
+ tcp.TCPOptionMaximumSegmentSize(max_seg_size=1460),
+ tcp.TCPOptionWindowScale(shift_cnt=9),
+ tcp.TCPOptionSACKPermitted(),
+ tcp.TCPOptionSACK(blocks=[(1, 2), (3, 4)], length=18),
+ tcp.TCPOptionTimestamps(ts_val=287454020, ts_ecr=1432778632),
+ tcp.TCPOptionUserTimeout(granularity=1, user_timeout=564),
+ tcp.TCPOptionAuthentication(
+ key_id=1, r_next_key_id=2,
+ mac=b'abcdefghijkl', length=16),
+ tcp.TCPOptionUnknown(value=b'foobar', kind=255, length=8),
+ tcp.TCPOptionUnknown(value=b'', kind=255, length=2),
+ ]
+ input_buf = (
+ b'\x00' # End of Option List
+ b'\x01' # No-Operation
+ b'\x02\x04\x05\xb4' # Maximum Segment Size
+ b'\x03\x03\x09' # Window Scale
+ b'\x04\x02' # SACK Permitted
+ b'\x05\x12' # SACK
+ b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04'
+ b'\x08\x0a' # Timestamps
+ b'\x11\x22\x33\x44\x55\x66\x77\x88'
+ b'\x1c\x04\x82\x34' # User Timeout Option
+ b'\x1d\x10\x01\x02' # TCP Authentication Option (TCP-AO)
+ b'abcdefghijkl'
+ b'\xff\x08' # Unknown with body
+ b'foobar'
+ b'\xff\x02' # Unknown
+ )
+
+ def test_serialize(self):
+ output_buf = bytearray()
+ for option in self.input_options:
+ output_buf += option.serialize()
+ eq_(self.input_buf, output_buf)
+
+ def test_parser(self):
+ buf = self.input_buf
+ output_options = []
+ while buf:
+ opt, buf = tcp.TCPOption.parser(buf)
+ output_options.append(opt)
+ eq_(str(self.input_options), str(output_options))
+
+ def test_json(self):
+ for option in self.input_options:
+ json_dict = option.to_jsondict()[option.__class__.__name__]
+ output_option = option.__class__.from_jsondict(json_dict)
+ eq_(str(option), str(output_option))
diff --git a/tests/unit/packet/test_udp.py b/tests/unit/packet/test_udp.py
new file mode 100644
index 00000000..0d7d0aa9
--- /dev/null
+++ b/tests/unit/packet/test_udp.py
@@ -0,0 +1,110 @@
+# 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 unittest
+import logging
+import struct
+from struct import *
+from nose.tools import *
+from ryu.ofproto import ether, inet
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet.udp import udp
+from ryu.lib.packet.ipv4 import ipv4
+from ryu.lib.packet import packet_utils
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger('test_udp')
+
+
+class Test_udp(unittest.TestCase):
+ """ Test case for udp
+ """
+ src_port = 6431
+ dst_port = 8080
+ total_length = 65507
+ csum = 12345
+ u = udp(src_port, dst_port, total_length, csum)
+ buf = pack(udp._PACK_STR, src_port, dst_port, total_length, csum)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.src_port, self.u.src_port)
+ eq_(self.dst_port, self.u.dst_port)
+ eq_(self.total_length, self.u.total_length)
+ eq_(self.csum, self.u.csum)
+
+ def test_parser(self):
+ r1, r2, _ = self.u.parser(self.buf)
+
+ eq_(self.src_port, r1.src_port)
+ eq_(self.dst_port, r1.dst_port)
+ eq_(self.total_length, r1.total_length)
+ eq_(self.csum, r1.csum)
+ eq_(None, r2)
+
+ def test_serialize(self):
+ src_port = 6431
+ dst_port = 8080
+ total_length = 0
+ csum = 0
+
+ src_ip = '192.168.10.1'
+ dst_ip = '192.168.100.1'
+ prev = ipv4(4, 5, 0, 0, 0, 0, 0, 64,
+ inet.IPPROTO_UDP, 0, src_ip, dst_ip)
+
+ u = udp(src_port, dst_port, total_length, csum)
+ buf = u.serialize(bytearray(), prev)
+ res = struct.unpack(udp._PACK_STR, buf)
+
+ eq_(res[0], src_port)
+ eq_(res[1], dst_port)
+ eq_(res[2], struct.calcsize(udp._PACK_STR))
+
+ # checksum
+ ph = struct.pack('!4s4sBBH',
+ addrconv.ipv4.text_to_bin(src_ip),
+ addrconv.ipv4.text_to_bin(dst_ip), 0, 17, res[2])
+ d = ph + buf + bytearray()
+ s = packet_utils.checksum(d)
+ eq_(0, s)
+
+ @raises(Exception)
+ def test_malformed_udp(self):
+ m_short_buf = self.buf[1:udp._MIN_LEN]
+ udp.parser(m_short_buf)
+
+ def test_default_args(self):
+ prev = ipv4(proto=inet.IPPROTO_UDP)
+ u = udp()
+ buf = u.serialize(bytearray(), prev)
+ res = struct.unpack(udp._PACK_STR, buf)
+
+ eq_(res[0], 1)
+ eq_(res[1], 1)
+ eq_(res[2], udp._MIN_LEN)
+
+ def test_json(self):
+ jsondict = self.u.to_jsondict()
+ u = udp.from_jsondict(jsondict['udp'])
+ eq_(str(self.u), str(u))
diff --git a/tests/unit/packet/test_vlan.py b/tests/unit/packet/test_vlan.py
new file mode 100644
index 00000000..b8e3a048
--- /dev/null
+++ b/tests/unit/packet/test_vlan.py
@@ -0,0 +1,265 @@
+# 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 unittest
+import logging
+import struct
+from struct import *
+from nose.tools import *
+from ryu.ofproto import ether, inet
+from ryu.lib.packet.ethernet import ethernet
+from ryu.lib.packet.packet import Packet
+from ryu.lib.packet.ipv4 import ipv4
+from ryu.lib.packet.vlan import vlan
+from ryu.lib.packet.vlan import svlan
+
+
+LOG = logging.getLogger('test_vlan')
+
+
+class Test_vlan(unittest.TestCase):
+ """ Test case for vlan
+ """
+
+ pcp = 0
+ cfi = 0
+ vid = 32
+ tci = pcp << 15 | cfi << 12 | vid
+ ethertype = ether.ETH_TYPE_IP
+
+ buf = pack(vlan._PACK_STR, tci, ethertype)
+
+ v = vlan(pcp, cfi, vid, ethertype)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.pcp, self.v.pcp)
+ eq_(self.cfi, self.v.cfi)
+ eq_(self.vid, self.v.vid)
+ eq_(self.ethertype, self.v.ethertype)
+
+ def test_parser(self):
+ res, ptype, _ = self.v.parser(self.buf)
+
+ eq_(res.pcp, self.pcp)
+ eq_(res.cfi, self.cfi)
+ eq_(res.vid, self.vid)
+ eq_(res.ethertype, self.ethertype)
+ eq_(ptype, ipv4)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.v.serialize(data, prev)
+
+ fmt = vlan._PACK_STR
+ res = struct.unpack(fmt, buf)
+
+ eq_(res[0], self.tci)
+ eq_(res[1], self.ethertype)
+
+ def _build_vlan(self):
+ src_mac = '00:07:0d:af:f4:54'
+ dst_mac = '00:00:00:00:00:00'
+ ethertype = ether.ETH_TYPE_8021Q
+ e = ethernet(dst_mac, src_mac, ethertype)
+
+ version = 4
+ header_length = 20
+ tos = 0
+ total_length = 24
+ identification = 0x8a5d
+ flags = 0
+ offset = 1480
+ ttl = 64
+ proto = inet.IPPROTO_ICMP
+ csum = 0xa7f2
+ src = '131.151.32.21'
+ dst = '131.151.32.129'
+ option = b'TEST'
+ ip = ipv4(version, header_length, tos, total_length, identification,
+ flags, offset, ttl, proto, csum, src, dst, option)
+
+ p = Packet()
+
+ p.add_protocol(e)
+ p.add_protocol(self.v)
+ p.add_protocol(ip)
+ p.serialize()
+
+ return p
+
+ def test_build_vlan(self):
+ p = self._build_vlan()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_8021Q)
+
+ v = self.find_protocol(p, "vlan")
+ ok_(v)
+ eq_(v.ethertype, ether.ETH_TYPE_IP)
+
+ ip = self.find_protocol(p, "ipv4")
+ ok_(ip)
+
+ eq_(v.pcp, self.pcp)
+ eq_(v.cfi, self.cfi)
+ eq_(v.vid, self.vid)
+ eq_(v.ethertype, self.ethertype)
+
+ @raises(Exception)
+ def test_malformed_vlan(self):
+ m_short_buf = self.buf[1:vlan._MIN_LEN]
+ vlan.parser(m_short_buf)
+
+ def test_json(self):
+ jsondict = self.v.to_jsondict()
+ v = vlan.from_jsondict(jsondict['vlan'])
+ eq_(str(self.v), str(v))
+
+
+class Test_svlan(unittest.TestCase):
+
+ pcp = 0
+ cfi = 0
+ vid = 32
+ tci = pcp << 15 | cfi << 12 | vid
+ ethertype = ether.ETH_TYPE_8021Q
+
+ buf = pack(svlan._PACK_STR, tci, ethertype)
+
+ sv = svlan(pcp, cfi, vid, ethertype)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def find_protocol(self, pkt, name):
+ for p in pkt.protocols:
+ if p.protocol_name == name:
+ return p
+
+ def test_init(self):
+ eq_(self.pcp, self.sv.pcp)
+ eq_(self.cfi, self.sv.cfi)
+ eq_(self.vid, self.sv.vid)
+ eq_(self.ethertype, self.sv.ethertype)
+
+ def test_parser(self):
+ res, ptype, _ = self.sv.parser(self.buf)
+
+ eq_(res.pcp, self.pcp)
+ eq_(res.cfi, self.cfi)
+ eq_(res.vid, self.vid)
+ eq_(res.ethertype, self.ethertype)
+ eq_(ptype, vlan)
+
+ def test_serialize(self):
+ data = bytearray()
+ prev = None
+ buf = self.sv.serialize(data, prev)
+
+ fmt = svlan._PACK_STR
+ res = struct.unpack(fmt, buf)
+
+ eq_(res[0], self.tci)
+ eq_(res[1], self.ethertype)
+
+ def _build_svlan(self):
+ src_mac = '00:07:0d:af:f4:54'
+ dst_mac = '00:00:00:00:00:00'
+ ethertype = ether.ETH_TYPE_8021AD
+ e = ethernet(dst_mac, src_mac, ethertype)
+
+ pcp = 0
+ cfi = 0
+ vid = 32
+ tci = pcp << 15 | cfi << 12 | vid
+ ethertype = ether.ETH_TYPE_IP
+ v = vlan(pcp, cfi, vid, ethertype)
+
+ version = 4
+ header_length = 20
+ tos = 0
+ total_length = 24
+ identification = 0x8a5d
+ flags = 0
+ offset = 1480
+ ttl = 64
+ proto = inet.IPPROTO_ICMP
+ csum = 0xa7f2
+ src = '131.151.32.21'
+ dst = '131.151.32.129'
+ option = b'TEST'
+ ip = ipv4(version, header_length, tos, total_length, identification,
+ flags, offset, ttl, proto, csum, src, dst, option)
+
+ p = Packet()
+
+ p.add_protocol(e)
+ p.add_protocol(self.sv)
+ p.add_protocol(v)
+ p.add_protocol(ip)
+ p.serialize()
+
+ return p
+
+ def test_build_svlan(self):
+ p = self._build_svlan()
+
+ e = self.find_protocol(p, "ethernet")
+ ok_(e)
+ eq_(e.ethertype, ether.ETH_TYPE_8021AD)
+
+ sv = self.find_protocol(p, "svlan")
+ ok_(sv)
+ eq_(sv.ethertype, ether.ETH_TYPE_8021Q)
+
+ v = self.find_protocol(p, "vlan")
+ ok_(v)
+ eq_(v.ethertype, ether.ETH_TYPE_IP)
+
+ ip = self.find_protocol(p, "ipv4")
+ ok_(ip)
+
+ eq_(sv.pcp, self.pcp)
+ eq_(sv.cfi, self.cfi)
+ eq_(sv.vid, self.vid)
+ eq_(sv.ethertype, self.ethertype)
+
+ @raises(Exception)
+ def test_malformed_svlan(self):
+ m_short_buf = self.buf[1:svlan._MIN_LEN]
+ svlan.parser(m_short_buf)
+
+ def test_json(self):
+ jsondict = self.sv.to_jsondict()
+ sv = svlan.from_jsondict(jsondict['svlan'])
+ eq_(str(self.sv), str(sv))
diff --git a/tests/unit/packet/test_vrrp.py b/tests/unit/packet/test_vrrp.py
new file mode 100644
index 00000000..71c52500
--- /dev/null
+++ b/tests/unit/packet/test_vrrp.py
@@ -0,0 +1,496 @@
+# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
+#
+# 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
+
+from __future__ import print_function
+
+import unittest
+import logging
+import six
+import struct
+import inspect
+
+from nose.tools import eq_, ok_
+from nose.tools import raises
+
+from ryu.ofproto import inet
+from ryu.lib.packet import ipv4
+from ryu.lib.packet import ipv6
+from ryu.lib.packet import packet
+from ryu.lib.packet import packet_utils
+from ryu.lib.packet import vrrp
+from ryu.lib import addrconv
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_vrrpv2(unittest.TestCase):
+ """ Test case for vrrp v2
+ """
+ version = vrrp.VRRP_VERSION_V2
+ type_ = vrrp.VRRP_TYPE_ADVERTISEMENT
+ vrid = 128
+ priority = 100
+ count_ip = 1
+ auth_type = vrrp.VRRP_AUTH_NO_AUTH
+ max_adver_int = 100
+ checksum = 0
+ ip_address = '192.168.0.1'
+ auth_data = (0, 0)
+ vrrpv2 = vrrp.vrrpv2.create(type_, vrid, priority, max_adver_int,
+ [ip_address])
+ buf = struct.pack(vrrp.vrrpv2._PACK_STR + '4sII',
+ vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V2, type_),
+ vrid, priority, count_ip,
+ auth_type, max_adver_int, checksum,
+ addrconv.ipv4.text_to_bin(ip_address),
+ auth_data[0], auth_data[1])
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.type_, self.vrrpv2.type)
+ eq_(self.vrid, self.vrrpv2.vrid)
+ eq_(self.priority, self.vrrpv2.priority)
+ eq_(self.count_ip, self.vrrpv2.count_ip)
+ eq_(self.auth_type, self.vrrpv2.auth_type)
+ eq_(1, len(self.vrrpv2.ip_addresses))
+ eq_(self.ip_address, self.vrrpv2.ip_addresses[0])
+ eq_(self.auth_data, self.vrrpv2.auth_data)
+
+ def test_parser(self):
+ vrrpv2, _cls, _ = self.vrrpv2.parser(self.buf)
+
+ eq_(self.version, vrrpv2.version)
+ eq_(self.type_, vrrpv2.type)
+ eq_(self.vrid, vrrpv2.vrid)
+ eq_(self.priority, vrrpv2.priority)
+ eq_(self.count_ip, vrrpv2.count_ip)
+ eq_(self.auth_type, vrrpv2.auth_type)
+ eq_(self.max_adver_int, vrrpv2.max_adver_int)
+ eq_(self.checksum, vrrpv2.checksum)
+ eq_(1, len(vrrpv2.ip_addresses))
+ eq_(str, type(vrrpv2.ip_addresses[0]))
+ eq_(self.ip_address, vrrpv2.ip_addresses[0])
+ eq_(self.auth_data, vrrpv2.auth_data)
+
+ def test_serialize(self):
+ src_ip = '192.168.0.1'
+ dst_ip = vrrp.VRRP_IPV4_DST_ADDRESS
+ prev = ipv4.ipv4(4, 5, 0, 0, 0, 0, 0, vrrp.VRRP_IPV4_TTL,
+ inet.IPPROTO_VRRP, 0, src_ip, dst_ip)
+
+ type_ = vrrp.VRRP_TYPE_ADVERTISEMENT
+ vrid = 5
+ priority = 10
+ max_adver_int = 30
+ ip_address = '192.168.0.2'
+ ip_addresses = [ip_address]
+
+ vrrp_ = vrrp.vrrpv2.create(
+ type_, vrid, priority, max_adver_int, ip_addresses)
+
+ buf = vrrp_.serialize(bytearray(), prev)
+ pack_str = vrrp.vrrpv2._PACK_STR + '4sII'
+ pack_len = struct.calcsize(pack_str)
+ res = struct.unpack(pack_str, six.binary_type(buf))
+ eq_(res[0], vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V2, type_))
+ eq_(res[1], vrid)
+ eq_(res[2], priority)
+ eq_(res[3], len(ip_addresses))
+ eq_(res[4], vrrp.VRRP_AUTH_NO_AUTH)
+ eq_(res[5], max_adver_int)
+ # res[6] is checksum
+ eq_(res[7], addrconv.ipv4.text_to_bin(ip_address))
+ eq_(res[8], 0)
+ eq_(res[9], 0)
+ eq_(len(buf), pack_len)
+
+ # checksum
+ s = packet_utils.checksum(buf)
+ eq_(0, s)
+
+ @raises(Exception)
+ def test_malformed_vrrpv2(self):
+ m_short_buf = self.buf[1:vrrp.vrrpv2._MIN_LEN]
+ vrrp.vrrp.parser(m_short_buf)
+
+ def test_create_packet(self):
+ primary_ip = '192.168.0.2'
+ p0 = self.vrrpv2.create_packet(primary_ip)
+ p0.serialize()
+ p1 = packet.Packet(six.binary_type(p0.data))
+ p1.serialize()
+ eq_(p0.data, p1.data)
+
+ def _test_is_valid(self, type_=None, vrid=None, priority=None,
+ max_adver_int=None):
+ if type_ is None:
+ type_ = self.type_
+ if vrid is None:
+ vrid = self.vrid
+ if priority is None:
+ priority = self.priority
+ if max_adver_int is None:
+ max_adver_int = self.max_adver_int
+
+ vrrp_ = vrrp.vrrpv2.create(type_, vrid, priority, max_adver_int,
+ [self.ip_address])
+ return vrrp_.is_valid()
+
+ def test_is_valid_ok(self):
+ ok_(self._test_is_valid())
+
+ def test_is_valid_ng_type(self):
+ ok_(not self._test_is_valid(type_=15))
+
+ def test_is_valid_ng_vrid_min(self):
+ vrid = vrrp.VRRP_VRID_MIN - 1
+ ok_(not self._test_is_valid(vrid=vrid))
+
+ def test_is_valid_ng_vrid_max(self):
+ vrid = vrrp.VRRP_VRID_MAX + 1
+ ok_(not self._test_is_valid(vrid=vrid))
+
+ def test_is_valid_ng_priority_min(self):
+ priority = vrrp.VRRP_PRIORITY_MIN - 1
+ ok_(not self._test_is_valid(priority=priority))
+
+ def test_is_valid_ng_priority_max(self):
+ priority = vrrp.VRRP_PRIORITY_MAX + 1
+ ok_(not self._test_is_valid(priority=priority))
+
+ def test_is_valid_ng_adver_min(self):
+ max_adver_int = vrrp.VRRP_V2_MAX_ADVER_INT_MIN - 1
+ ok_(not self._test_is_valid(max_adver_int=max_adver_int))
+
+ def test_is_valid_ng_adver_max(self):
+ max_adver_int = vrrp.VRRP_V2_MAX_ADVER_INT_MAX + 1
+ ok_(not self._test_is_valid(max_adver_int=max_adver_int))
+
+ def test_to_string(self):
+ vrrpv2_values = {'version': self.version,
+ 'type': self.type_,
+ 'vrid': self.vrid,
+ 'priority': self.priority,
+ 'count_ip': self.count_ip,
+ 'max_adver_int': self.max_adver_int,
+ 'checksum': self.vrrpv2.checksum,
+ 'ip_addresses': [self.ip_address],
+ 'auth_type': self.auth_type,
+ 'auth_data': self.auth_data,
+ 'identification': self.vrrpv2.identification}
+ _vrrpv2_str = ','.join(['%s=%s' % (k, repr(vrrpv2_values[k]))
+ for k, v in inspect.getmembers(self.vrrpv2)
+ if k in vrrpv2_values])
+ vrrpv2_str = '%s(%s)' % (vrrp.vrrpv2.__name__, _vrrpv2_str)
+
+ eq_(str(self.vrrpv2), vrrpv2_str)
+ eq_(repr(self.vrrpv2), vrrpv2_str)
+
+
+class Test_vrrpv3_ipv4(unittest.TestCase):
+ """ Test case for vrrp v3 IPv4
+ """
+ version = vrrp.VRRP_VERSION_V3
+ type_ = vrrp.VRRP_TYPE_ADVERTISEMENT
+ vrid = 128
+ priority = 99
+ count_ip = 1
+ max_adver_int = 111
+ checksum = 0
+ ip_address = '192.168.0.1'
+ vrrpv3 = vrrp.vrrpv3.create(type_, vrid, priority, max_adver_int,
+ [ip_address])
+ buf = struct.pack(vrrp.vrrpv3._PACK_STR + '4s',
+ vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V3, type_),
+ vrid, priority, count_ip,
+ max_adver_int, checksum,
+ addrconv.ipv4.text_to_bin(ip_address))
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.type_, self.vrrpv3.type)
+ eq_(self.vrid, self.vrrpv3.vrid)
+ eq_(self.priority, self.vrrpv3.priority)
+ eq_(self.count_ip, self.vrrpv3.count_ip)
+ eq_(1, len(self.vrrpv3.ip_addresses))
+ eq_(self.ip_address, self.vrrpv3.ip_addresses[0])
+
+ def test_parser(self):
+ vrrpv3, _cls, _ = self.vrrpv3.parser(self.buf)
+
+ eq_(self.version, vrrpv3.version)
+ eq_(self.type_, vrrpv3.type)
+ eq_(self.vrid, vrrpv3.vrid)
+ eq_(self.priority, vrrpv3.priority)
+ eq_(self.count_ip, vrrpv3.count_ip)
+ eq_(self.max_adver_int, vrrpv3.max_adver_int)
+ eq_(self.checksum, vrrpv3.checksum)
+ eq_(1, len(vrrpv3.ip_addresses))
+ eq_(str, type(vrrpv3.ip_addresses[0]))
+ eq_(self.ip_address, vrrpv3.ip_addresses[0])
+
+ def test_serialize(self):
+ src_ip = '192.168.0.1'
+ dst_ip = vrrp.VRRP_IPV4_DST_ADDRESS
+ prev = ipv4.ipv4(4, 5, 0, 0, 0, 0, 0, vrrp.VRRP_IPV4_TTL,
+ inet.IPPROTO_VRRP, 0, src_ip, dst_ip)
+
+ type_ = vrrp.VRRP_TYPE_ADVERTISEMENT
+ vrid = 5
+ priority = 10
+ max_adver_int = 30
+ ip_address = '192.168.0.2'
+ ip_addresses = [ip_address]
+
+ vrrp_ = vrrp.vrrpv3.create(
+ type_, vrid, priority, max_adver_int, ip_addresses)
+
+ buf = vrrp_.serialize(bytearray(), prev)
+ print(len(buf), type(buf), buf)
+ pack_str = vrrp.vrrpv3._PACK_STR + '4s'
+ pack_len = struct.calcsize(pack_str)
+ res = struct.unpack(pack_str, six.binary_type(buf))
+ eq_(res[0], vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V3, type_))
+ eq_(res[1], vrid)
+ eq_(res[2], priority)
+ eq_(res[3], len(ip_addresses))
+ eq_(res[4], max_adver_int)
+ # res[5] is checksum
+ eq_(res[6], addrconv.ipv4.text_to_bin(ip_address))
+ eq_(len(buf), pack_len)
+ print(res)
+
+ # checksum
+ ph = struct.pack('!4s4sxBH',
+ addrconv.ipv4.text_to_bin(src_ip),
+ addrconv.ipv4.text_to_bin(dst_ip),
+ inet.IPPROTO_VRRP, pack_len)
+ s = packet_utils.checksum(ph + buf)
+ eq_(0, s)
+
+ @raises(Exception)
+ def test_malformed_vrrpv3(self):
+ m_short_buf = self.buf[1:vrrp.vrrpv3._MIN_LEN]
+ vrrp.vrrp.parser(m_short_buf)
+
+ def test_create_packet(self):
+ primary_ip = '192.168.0.2'
+ p0 = self.vrrpv3.create_packet(primary_ip)
+ p0.serialize()
+ p1 = packet.Packet(six.binary_type(p0.data))
+ p1.serialize()
+ eq_(p0.data, p1.data)
+
+ def _test_is_valid(self, type_=None, vrid=None, priority=None,
+ max_adver_int=None):
+ if type_ is None:
+ type_ = self.type_
+ if vrid is None:
+ vrid = self.vrid
+ if priority is None:
+ priority = self.priority
+ if max_adver_int is None:
+ max_adver_int = self.max_adver_int
+
+ vrrp_ = vrrp.vrrpv3.create(type_, vrid, priority, max_adver_int,
+ [self.ip_address])
+ return vrrp_.is_valid()
+
+ def test_is_valid_ok(self):
+ ok_(self._test_is_valid())
+
+ def test_is_valid_ng_type(self):
+ ok_(not self._test_is_valid(type_=15))
+
+ def test_is_valid_ng_vrid_min(self):
+ vrid = vrrp.VRRP_VRID_MIN - 1
+ ok_(not self._test_is_valid(vrid=vrid))
+
+ def test_is_valid_ng_vrid_max(self):
+ vrid = vrrp.VRRP_VRID_MAX + 1
+ ok_(not self._test_is_valid(vrid=vrid))
+
+ def test_is_valid_ng_priority_min(self):
+ priority = vrrp.VRRP_PRIORITY_MIN - 1
+ ok_(not self._test_is_valid(priority=priority))
+
+ def test_is_valid_ng_priority_max(self):
+ priority = vrrp.VRRP_PRIORITY_MAX + 1
+ ok_(not self._test_is_valid(priority=priority))
+
+ def test_is_valid_ng_adver_min(self):
+ max_adver_int = vrrp.VRRP_V3_MAX_ADVER_INT_MIN - 1
+ ok_(not self._test_is_valid(max_adver_int=max_adver_int))
+
+ def test_is_valid_ng_adver_max(self):
+ max_adver_int = vrrp.VRRP_V3_MAX_ADVER_INT_MAX + 1
+ ok_(not self._test_is_valid(max_adver_int=max_adver_int))
+
+ def test_to_string(self):
+ vrrpv3_values = {'version': self.version,
+ 'type': self.type_,
+ 'vrid': self.vrid,
+ 'priority': self.priority,
+ 'count_ip': self.count_ip,
+ 'max_adver_int': self.max_adver_int,
+ 'checksum': self.vrrpv3.checksum,
+ 'ip_addresses': [self.ip_address],
+ 'auth_type': None,
+ 'auth_data': None,
+ 'identification': self.vrrpv3.identification}
+ _vrrpv3_str = ','.join(['%s=%s' % (k, repr(vrrpv3_values[k]))
+ for k, v in inspect.getmembers(self.vrrpv3)
+ if k in vrrpv3_values])
+ vrrpv3_str = '%s(%s)' % (vrrp.vrrpv3.__name__, _vrrpv3_str)
+
+ eq_(str(self.vrrpv3), vrrpv3_str)
+ eq_(repr(self.vrrpv3), vrrpv3_str)
+
+
+class Test_vrrpv3_ipv6(unittest.TestCase):
+ """ Test case for vrrp v3 IPv6
+ """
+ version = vrrp.VRRP_VERSION_V3
+ type_ = vrrp.VRRP_TYPE_ADVERTISEMENT
+ vrid = 128
+ priority = 99
+ count_ip = 1
+ max_adver_int = 111
+ checksum = 0
+ ip_address = '2001:db8:2000::1'
+ vrrpv3 = vrrp.vrrpv3.create(type_, vrid, priority, max_adver_int,
+ [ip_address])
+ buf = struct.pack(vrrp.vrrpv3._PACK_STR + '16s',
+ vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V3, type_),
+ vrid, priority, count_ip,
+ max_adver_int, checksum,
+ addrconv.ipv6.text_to_bin(ip_address))
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_init(self):
+ eq_(self.type_, self.vrrpv3.type)
+ eq_(self.vrid, self.vrrpv3.vrid)
+ eq_(self.priority, self.vrrpv3.priority)
+ eq_(self.count_ip, self.vrrpv3.count_ip)
+ eq_(1, len(self.vrrpv3.ip_addresses))
+ eq_(self.ip_address, self.vrrpv3.ip_addresses[0])
+
+ def test_parser(self):
+ vrrpv3, _cls, _ = self.vrrpv3.parser(self.buf)
+
+ eq_(self.version, vrrpv3.version)
+ eq_(self.type_, vrrpv3.type)
+ eq_(self.vrid, vrrpv3.vrid)
+ eq_(self.priority, vrrpv3.priority)
+ eq_(self.count_ip, vrrpv3.count_ip)
+ eq_(self.max_adver_int, vrrpv3.max_adver_int)
+ eq_(self.checksum, vrrpv3.checksum)
+ eq_(1, len(vrrpv3.ip_addresses))
+ eq_(str, type(vrrpv3.ip_addresses[0]))
+ eq_(self.ip_address, vrrpv3.ip_addresses[0])
+
+ def test_serialize(self):
+ src_ip = '2001:db8:2000::1'
+ dst_ip = vrrp.VRRP_IPV6_DST_ADDRESS
+ prev = ipv6.ipv6(6, 0, 0, 0, inet.IPPROTO_VRRP,
+ vrrp.VRRP_IPV6_HOP_LIMIT, src_ip, dst_ip)
+
+ type_ = vrrp.VRRP_TYPE_ADVERTISEMENT
+ vrid = 5
+ priority = 10
+ max_adver_int = 30
+ ip_address = '2001:db8:2000::2'
+ ip_addresses = [ip_address]
+
+ vrrp_ = vrrp.vrrpv3.create(
+ type_, vrid, priority, max_adver_int, ip_addresses)
+
+ buf = vrrp_.serialize(bytearray(), prev)
+ print(len(buf), type(buf), buf)
+ pack_str = vrrp.vrrpv3._PACK_STR + '16s'
+ pack_len = struct.calcsize(pack_str)
+ res = struct.unpack(pack_str, six.binary_type(buf))
+ eq_(res[0], vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V3, type_))
+ eq_(res[1], vrid)
+ eq_(res[2], priority)
+ eq_(res[3], len(ip_addresses))
+ eq_(res[4], max_adver_int)
+ # res[5] is checksum
+ eq_(res[6], addrconv.ipv6.text_to_bin(ip_address))
+ eq_(len(buf), pack_len)
+ print(res)
+
+ # checksum
+ ph = struct.pack('!16s16sI3xB',
+ addrconv.ipv6.text_to_bin(src_ip),
+ addrconv.ipv6.text_to_bin(dst_ip),
+ pack_len, inet.IPPROTO_VRRP)
+ s = packet_utils.checksum(ph + buf)
+ eq_(0, s)
+
+ @raises(Exception)
+ def test_malformed_vrrpv3(self):
+ m_short_buf = self.buf[1:vrrp.vrrpv3._MIN_LEN]
+ vrrp.vrrp.parser(m_short_buf)
+
+ def test_create_packet(self):
+ primary_ip = '2001:db8:2000::3'
+ p0 = self.vrrpv3.create_packet(primary_ip)
+ p0.serialize()
+ print(len(p0.data), p0.data)
+ p1 = packet.Packet(six.binary_type(p0.data))
+ p1.serialize()
+ print(len(p0.data), p0.data)
+ print(len(p1.data), p1.data)
+ eq_(p0.data, p1.data)
+
+ def test_to_string(self):
+ vrrpv3_values = {'version': self.version,
+ 'type': self.type_,
+ 'vrid': self.vrid,
+ 'priority': self.priority,
+ 'count_ip': self.count_ip,
+ 'max_adver_int': self.max_adver_int,
+ 'checksum': self.vrrpv3.checksum,
+ 'ip_addresses': [self.ip_address],
+ 'auth_type': None,
+ 'auth_data': None,
+ 'identification': self.vrrpv3.identification}
+ _vrrpv3_str = ','.join(['%s=%s' % (k, repr(vrrpv3_values[k]))
+ for k, v in inspect.getmembers(self.vrrpv3)
+ if k in vrrpv3_values])
+ vrrpv3_str = '%s(%s)' % (vrrp.vrrpv3.__name__, _vrrpv3_str)
+
+ eq_(str(self.vrrpv3), vrrpv3_str)
+ eq_(repr(self.vrrpv3), vrrpv3_str)
diff --git a/tests/unit/packet/test_vxlan.py b/tests/unit/packet/test_vxlan.py
new file mode 100644
index 00000000..8cace581
--- /dev/null
+++ b/tests/unit/packet/test_vxlan.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2016 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 unittest
+
+from nose.tools import eq_
+from nose.tools import raises
+
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import vxlan
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Test_vxlan(unittest.TestCase):
+ """
+ Test case for VXLAN (RFC 7348) header encoder/decoder class.
+ """
+
+ vni = 0x123456
+ buf = (
+ b'\x08\x00\x00\x00' # flags = R|R|R|R|I|R|R|R (8 bits)
+ b'\x12\x34\x56\x00' # vni = 0x123456 (24 bits)
+ b'test_payload' # for test
+ )
+ pkt = vxlan.vxlan(vni)
+ jsondict = {
+ 'vxlan': {
+ 'vni': vni
+ }
+ }
+
+ def test_init(self):
+ eq_(self.vni, self.pkt.vni)
+
+ def test_parser(self):
+ parsed_pkt, next_proto_cls, rest_buf = vxlan.vxlan.parser(self.buf)
+ eq_(self.vni, parsed_pkt.vni)
+ eq_(ethernet.ethernet, next_proto_cls)
+ eq_(b'test_payload', rest_buf)
+
+ @raises(AssertionError)
+ def test_invalid_flags(self):
+ invalid_flags_bug = (
+ b'\x00\x00\x00\x00' # all bits are set to zero
+ b'\x12\x34\x56\x00' # vni = 0x123456 (24 bits)
+ )
+ vxlan.vxlan.parser(invalid_flags_bug)
+
+ def test_serialize(self):
+ serialized_buf = self.pkt.serialize(payload=None, prev=None)
+ eq_(self.buf[:vxlan.vxlan._MIN_LEN], serialized_buf)
+
+ def test_from_jsondict(self):
+ pkt_from_json = vxlan.vxlan.from_jsondict(
+ self.jsondict[vxlan.vxlan.__name__])
+ eq_(self.vni, pkt_from_json.vni)
+
+ def test_to_jsondict(self):
+ jsondict_from_pkt = self.pkt.to_jsondict()
+ eq_(self.jsondict, jsondict_from_pkt)
+
+ def test_vni_from_bin(self):
+ vni = vxlan.vni_from_bin(b'\x12\x34\x56')
+ eq_(self.vni, vni)
+
+ def test_vni_to_bin(self):
+ eq_(b'\x12\x34\x56', vxlan.vni_to_bin(self.vni))
diff --git a/tests/unit/packet/test_zebra.py b/tests/unit/packet/test_zebra.py
new file mode 100644
index 00000000..19ff88de
--- /dev/null
+++ b/tests/unit/packet/test_zebra.py
@@ -0,0 +1,66 @@
+# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+
+import os
+import sys
+import unittest
+
+from nose.tools import eq_
+from nose.tools import ok_
+import six
+
+from ryu.lib import pcaplib
+from ryu.lib.packet import packet
+from ryu.lib.packet import zebra
+from ryu.utils import binary_str
+
+
+PCAP_DATA_DIR = os.path.join(
+ os.path.dirname(sys.modules[__name__].__file__),
+ '../../packet_data/pcap/')
+
+
+class Test_zebra(unittest.TestCase):
+ """
+ Test case for ryu.lib.packet.zebra.
+ """
+
+ def test_pcap(self):
+ files = [
+ 'zebra_v2',
+ 'zebra_v3',
+ ]
+
+ for f in files:
+ zebra_pcap_file = os.path.join(PCAP_DATA_DIR, f + '.pcap')
+ # print('*** testing %s' % zebra_pcap_file)
+
+ for _, buf in pcaplib.Reader(open(zebra_pcap_file, 'rb')):
+ # Checks if Zebra message can be parsed as expected.
+ pkt = packet.Packet(buf)
+ zebra_pkts = pkt.get_protocols(zebra.ZebraMessage)
+ for zebra_pkt in zebra_pkts:
+ ok_(isinstance(zebra_pkt, zebra.ZebraMessage),
+ 'Failed to parse Zebra message: %s' % pkt)
+ ok_(not isinstance(pkt.protocols[-1],
+ (six.binary_type, bytearray)),
+ 'Some messages could not be parsed: %s' % pkt)
+
+ # Checks if Zebra message can be serialized as expected.
+ pkt.serialize()
+ eq_(buf, pkt.data,
+ "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))