Signed-off-by: itoyuichi <[email protected]>
---
 ryu/lib/packet/ipv6.py             |   52 +++++++++++++++++++++
 ryu/tests/unit/packet/test_ipv6.py |   89 ++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)

diff --git a/ryu/lib/packet/ipv6.py b/ryu/lib/packet/ipv6.py
index 747ec40..ff50cdf 100644
--- a/ryu/lib/packet/ipv6.py
+++ b/ryu/lib/packet/ipv6.py
@@ -324,3 +324,55 @@ class option(stringify.StringifyMixin):

     def __len__(self):
         return self._MIN_LEN + self.len_
+
+
[email protected]_header_type(inet.IPPROTO_FRAGMENT)
+class fragment(header):
+    """IPv6 (RFC 2460) fragment header encoder/decoder class.
+
+    This is used with ryu.lib.packet.ipv6.ipv6.
+
+    An instance has the following attributes at least.
+    Most of them are same to the on-wire counterparts but in host byte order.
+    __init__ takes the corresponding args in this order.
+
+    .. tabularcolumns:: |l|L|
+
+    ============== =======================================
+    Attribute      Description
+    ============== =======================================
+    offset         offset, in 8-octet units, relative to
+                   the start of the fragmentable part of
+                   the original packet.
+    more           1 means more fragments follow;
+                   0 means last fragment.
+    id\_           packet identification value.
+    ============== =======================================
+    """
+    TYPE = inet.IPPROTO_FRAGMENT
+
+    _PACK_STR = '!BxHI'
+    _MIN_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, offset, more, id_):
+        super(fragment, self).__init__()
+        self.offset = offset
+        self.more = more
+        self.id_ = id_
+
+    @classmethod
+    def parser(cls, buf):
+        (nxt, off_m, id_) = struct.unpack_from(cls._PACK_STR, buf)
+        offset = off_m >> 3
+        more = off_m & 0x1
+        ret = cls(offset, more, id_)
+        ret.set_nxt(nxt)
+        return ret
+
+    def serialize(self):
+        off_m = (self.offset << 3 | self.more)
+        buf = struct.pack(self._PACK_STR, self.nxt, off_m, self.id_)
+        return buf
+
+    def __len__(self):
+        return self._MIN_LEN
diff --git a/ryu/tests/unit/packet/test_ipv6.py 
b/ryu/tests/unit/packet/test_ipv6.py
index 5a71c56..42c5523 100644
--- a/ryu/tests/unit/packet/test_ipv6.py
+++ b/ryu/tests/unit/packet/test_ipv6.py
@@ -111,6 +111,27 @@ class Test_ipv6(unittest.TestCase):
             addrconv.ipv6.text_to_bin(self.dst))
         self.buf += self.dst_opts.serialize()

+    def setUp_with_fragment(self):
+        self.fragment_offset = 50
+        self.fragment_more = 1
+        self.fragment_id = 123
+        self.fragment = ipv6.fragment(
+            self.fragment_offset, self.fragment_more, self.fragment_id)
+        self.ext_hdrs = [self.fragment]
+        self.payload_length += len(self.fragment)
+        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.fragment.nxt = self.nxt
+        self.nxt = self.fragment.TYPE
+        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 tearDown(self):
         pass

@@ -133,6 +154,10 @@ class Test_ipv6(unittest.TestCase):
         self.setUp_with_dst_opts()
         self.test_init()

+    def test_init_with_fragment(self):
+        self.setUp_with_fragment()
+        self.test_init()
+
     def test_parser(self):
         _res = self.ip.parser(str(self.buf))
         if type(_res) is tuple:
@@ -158,6 +183,10 @@ class Test_ipv6(unittest.TestCase):
         self.setUp_with_dst_opts()
         self.test_parser()

+    def test_parser_with_fragment(self):
+        self.setUp_with_fragment()
+        self.test_parser()
+
     def test_serialize(self):
         data = bytearray()
         prev = None
@@ -192,6 +221,16 @@ class Test_ipv6(unittest.TestCase):
         dst_opts = ipv6.dst_opts.parser(str(buf[ipv6.ipv6._MIN_LEN:]))
         eq_(repr(self.dst_opts), repr(dst_opts))

+    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(str(buf[ipv6.ipv6._MIN_LEN:]))
+        eq_(repr(self.fragment), repr(fragment))
+
     def test_to_string(self):
         ipv6_values = {'version': self.version,
                        'traffic_class': self.traffic_class,
@@ -218,6 +257,10 @@ class Test_ipv6(unittest.TestCase):
         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_len(self):
         eq_(len(self.ip), 40)

@@ -229,6 +272,10 @@ class Test_ipv6(unittest.TestCase):
         self.setUp_with_dst_opts()
         eq_(len(self.ip), 40 + len(self.dst_opts))

+    def test_len_with_fragment(self):
+        self.setUp_with_fragment()
+        eq_(len(self.ip), 40 + len(self.fragment))
+

 class Test_hop_opts(unittest.TestCase):

@@ -444,3 +491,45 @@ class Test_option_padN(Test_option):
         res = struct.unpack_from(self.form, buf)
         eq_(self.type_, res[0])
         eq_(self.len_, res[1])
+
+
+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.offset, self.more, self.id_)
+        self.fragment.set_nxt(self.nxt)
+
+        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, str(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))
-- 
1.7.10.4


------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. 
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to