diff options
Diffstat (limited to 'ryu/lib/packet/icmpv6.py')
-rw-r--r-- | ryu/lib/packet/icmpv6.py | 68 |
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 |