summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHIYAMA Manabu <hiyama.manabu@po.ntts.co.jp>2013-02-21 11:29:24 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2013-02-24 12:50:14 +0900
commit4c666748776fddc85e823b8bc39d3f7cb147a944 (patch)
treef8b365dff2ed0c61aa56b613962e468d7bf18676
parenta3cc10b8ec2fec40b72d95a6276d6ec719711086 (diff)
packet lib: fix icmpv6.nd_s.parser() and support NDP option type
This patch fixes parser error if there is no NDP option, and support the class to handle the NDP option. I have implemented only the option type = 1 and 2. We also need to implement other type, but this is enough in mininet for now. > Traceback (most recent call last): > (...) > File "/usr/local/lib/python2.7/dist-packages/ryu-1.6-py2.7.egg/ryu/lib/packet/icmpv6.py", line 87, in parser > msg.data = cls_.parser(buf, offset) > File "/usr/local/lib/python2.7/dist-packages/ryu-1.6-py2.7.egg/ryu/lib/packet/icmpv6.py", line 134, in parser > buf, offset) > error: unpack_from requires a buffer of at least 28 bytes Signed-off-by: HIYAMA Manabu <hiyama.manabu@po.ntts.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/packet/icmpv6.py68
1 files changed, 59 insertions, 9 deletions
diff --git a/ryu/lib/packet/icmpv6.py b/ryu/lib/packet/icmpv6.py
index 3f8ab2fe..eef450fe 100644
--- a/ryu/lib/packet/icmpv6.py
+++ b/ryu/lib/packet/icmpv6.py
@@ -116,23 +116,74 @@ class icmpv6(packet_base.PacketBase):
@icmpv6.register_icmpv6_type(ND_NEIGHBOR_SOLICIT, ND_NEIGHBOR_ADVERT)
-class nd_s(object):
- _PACK_STR = '!I16sBB6s'
+class nd_neighbor(object):
+ _PACK_STR = '!I16s'
_MIN_LEN = struct.calcsize(_PACK_STR)
+ _ND_OPTION_TYPES = {}
- def __init__(self, res, dst, type_, length, hw_src, data=None):
+ # ND option type
+ ND_OPTION_SLA = 1 # Source Link-Layer Address
+ ND_OPTION_TLA = 2 # Target Link-Layer Address
+ ND_OPTION_PI = 3 # Prefix Information
+ ND_OPTION_RH = 4 # Redirected Header
+ ND_OPTION_MTU = 5 # MTU
+
+ @staticmethod
+ def register_nd_option_type(*args):
+ def _register_nd_option_type(cls):
+ for type_ in args:
+ nd_neighbor._ND_OPTION_TYPES[type_] = cls
+ return cls
+ return _register_nd_option_type
+
+ def __init__(self, res, dst, type_=None, length=None, data=None):
self.res = res << 29
self.dst = dst
self.type_ = type_
self.length = length
+ self.data = data
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (res, dst) = struct.unpack_from(cls._PACK_STR, buf, offset)
+ msg = cls(res, dst)
+ offset += cls._MIN_LEN
+ if len(buf) > offset:
+ (msg.type_, msg.length) = struct.unpack_from('!BB', buf, offset)
+ cls_ = cls._ND_OPTION_TYPES.get(msg.type_, None)
+ if cls_:
+ msg.data = cls_.parser(buf, offset)
+ else:
+ msg.data = buf[offset:]
+
+ return msg
+
+ def serialize(self):
+ hdr = bytearray(struct.pack(nd_neighbor._PACK_STR, self.res, self.dst))
+
+ if self.type_ is not None:
+ hdr += bytearray(struct.pack('!BB', self.type_, self.length))
+ if self.type_ in nd_neighbor._ND_OPTION_TYPES:
+ hdr += self.data.serialize()
+ elif self.data is not None:
+ hdr += bytearray(self.data)
+
+ return hdr
+
+
+@nd_neighbor.register_nd_option_type(nd_neighbor.ND_OPTION_SLA, nd_neighbor.ND_OPTION_TLA)
+class nd_option_la(object):
+ _PACK_STR = '!6s'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+
+ def __init__(self, hw_src, data=None):
self.hw_src = hw_src
self.data = data
@classmethod
def parser(cls, buf, offset):
- (res, dst, type_, length, hw_src) = struct.unpack_from(cls._PACK_STR,
- buf, offset)
- msg = cls(res, dst, type_, length, hw_src)
+ (hw_src, ) = struct.unpack_from(cls._PACK_STR, buf, offset)
+ msg = cls(hw_src)
offset += cls._MIN_LEN
if len(buf) > offset:
msg.data = buf[offset:]
@@ -140,11 +191,10 @@ class nd_s(object):
return msg
def serialize(self):
- hdr = bytearray(struct.pack(nd_s._PACK_STR, self.res, self.dst,
- self.type_, self.length, self.hw_src))
+ hdr = bytearray(struct.pack(self._PACK_STR, self.hw_src))
if self.data is not None:
- hdr += self.data
+ hdr += bytearray(self.data)
return hdr