diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2014-07-02 18:16:52 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2014-07-03 00:09:23 +0900 |
commit | f96435bcfa57d45e01d22aa96f8567545e26f6e7 (patch) | |
tree | 4ac182a2cc7a0d30846d30e6e178446a32ea52ec | |
parent | fdce89a0def2b20d5dffda541207e2d482e2b652 (diff) |
ospf: support for opaque message
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/lib/packet/ospf.py | 109 |
1 files changed, 92 insertions, 17 deletions
diff --git a/ryu/lib/packet/ospf.py b/ryu/lib/packet/ospf.py index 6f40a82c..368016d2 100644 --- a/ryu/lib/packet/ospf.py +++ b/ryu/lib/packet/ospf.py @@ -67,6 +67,7 @@ ROUTER_LSA_SHORTCUT = 0x20 # Shortcut-ABR specific flag AS_EXTERNAL_METRIC = 0x80 +OSPF_OPAQUE_TYPE_UNKNOWN = 0 class InvalidChecksum(Exception): pass @@ -115,11 +116,16 @@ class LSAHeader(StringifyMixin): def __init__(self, ls_age=0, options=0, type_=OSPF_UNKNOWN_LSA, id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0, - checksum=None, length=None): + checksum=0, length=0, opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, + opaque_id=0): self.ls_age = ls_age self.options = options self.type_ = type_ - self.id_ = id_ + if self.type_ < OSPF_OPAQUE_LINK_LSA: + self.id_ = id_ + else: + self.opaque_type = opaque_type + self.opaque_id = opaque_id self.adv_router = adv_router self.ls_seqnum = ls_seqnum self.checksum = checksum @@ -132,23 +138,36 @@ class LSAHeader(StringifyMixin): '%d < %d' % (len(buf), cls._HDR_LEN)) (ls_age, options, type_, id_, adv_router, ls_seqnum, checksum, length,) = struct.unpack_from(cls._HDR_PACK_STR, buffer(buf)) - id_ = addrconv.ipv4.bin_to_text(id_) adv_router = addrconv.ipv4.bin_to_text(adv_router) rest = buf[cls._HDR_LEN:] + lsacls = LSA._lookup_type(type_) - return { + value = { "ls_age": ls_age, "options": options, "type_": type_, - "id_": id_, "adv_router": adv_router, "ls_seqnum": ls_seqnum, "checksum": checksum, "length": length, - }, rest + } + + if issubclass(lsacls, OpaqueLSA): + (id_,) = struct.unpack_from('!I', buffer(id_)) + value['opaque_type'] = (id_ & 0xff000000) >> 24 + value['opaque_id'] = (id_ & 0xffffff) + else: + value['id_'] = addrconv.ipv4.bin_to_text(id_) + + return value, rest def serialize(self): - id_ = addrconv.ipv4.text_to_bin(self.id_) + if self.type_ < OSPF_OPAQUE_LINK_LSA: + id_ = addrconv.ipv4.text_to_bin(self.id_) + else: + id_ = (self.opaque_type << 24) + self.opaque_id + (id_,) = struct.unpack_from('4s', struct.pack('I', id_)) + adv_router = addrconv.ipv4.text_to_bin(self.adv_router) return bytearray(struct.pack(self._HDR_PACK_STR, self.ls_age, self.options, self.type_, id_, adv_router, @@ -158,9 +177,15 @@ class LSAHeader(StringifyMixin): class LSA(_TypeDisp, StringifyMixin): def __init__(self, ls_age=0, options=0, type_=OSPF_UNKNOWN_LSA, id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0, - checksum=None, length=None): - self.header = LSAHeader(ls_age, options, type_, id_, adv_router, - ls_seqnum, 0, 0) + checksum=0, length=0, opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, + opaque_id=0): + if type_ < OSPF_OPAQUE_LINK_LSA: + self.header = LSAHeader(ls_age, options, type_, id_, adv_router, + ls_seqnum, 0, 0) + else: + self.header = LSAHeader(ls_age, options, type_, 0, adv_router, + ls_seqnum, 0, 0, opaque_type, opaque_id) + if not (checksum or length): tail = self.serialize_tail() length = self.header._HDR_LEN + len(tail) @@ -173,6 +198,9 @@ class LSA(_TypeDisp, StringifyMixin): @classmethod def parser(cls, buf): hdr, rest = LSAHeader.parser(buf) + if len(buf) < hdr['length']: + raise stream_parser.StreamParser.TooSmallException( + '%d < %d' % (len(buf), hdr['length'])) # exclude ls_age for checksum calculation csum = packet_utils.fletcher_checksum(buf[2:hdr['length']], 14) if csum != hdr['checksum']: @@ -181,7 +209,10 @@ class LSA(_TypeDisp, StringifyMixin): subcls = cls._lookup_type(hdr['type_']) body = rest[:hdr['length'] - LSAHeader._HDR_LEN] rest = rest[hdr['length'] - LSAHeader._HDR_LEN:] - kwargs = subcls.parser(body) + if issubclass(subcls, OpaqueLSA): + kwargs = subcls.parser(body, hdr['opaque_type']) + else: + kwargs = subcls.parser(body) kwargs.update(hdr) return subcls(**kwargs), subcls, rest @@ -384,19 +415,63 @@ class NSSAExternalLSA(LSA): pass +class OpaqueBody(StringifyMixin, _TypeDisp): + def __init__(self, tlvs=[]): + self.tlvs = tlvs + + def serialize(self): + return reduce(lambda a, b: a + b, + (tlv.serialize() for tlv in self.tlvs)) + + +class OpaqueLSA(LSA): + @classmethod + def parser(cls, buf, opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN): + opaquecls = OpaqueBody._lookup_type(opaque_type) + if opaquecls: + data = opaquecls.parser(buf) + else: + data = buf + return {'data': data} + + def serialize_tail(self): + if isinstance(self.data, OpaqueBody): + return self.data.serialize() + else: + return self.data + + @LSA.register_type(OSPF_OPAQUE_LINK_LSA) -class LocalOpaqueLSA(LSA): - pass +class LocalOpaqueLSA(OpaqueLSA): + def __init__(self, ls_age=0, options=0, type_=OSPF_OPAQUE_LINK_LSA, + adv_router='0.0.0.0', ls_seqnum=0, checksum=0, length=0, + opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, opaque_id=0, data=None): + self.data = data + super(LocalOpaqueLSA, self).__init__(ls_age, options, type_, 0, + adv_router, ls_seqnum, checksum, + length, opaque_type, opaque_id) @LSA.register_type(OSPF_OPAQUE_AREA_LSA) -class AreaOpaqueLSA(LSA): - pass +class AreaOpaqueLSA(OpaqueLSA): + def __init__(self, ls_age=0, options=0, type_=OSPF_OPAQUE_AREA_LSA, + adv_router='0.0.0.0', ls_seqnum=0, checksum=0, length=0, + opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, opaque_id=0, data=None): + self.data = data + super(AreaOpaqueLSA, self).__init__(ls_age, options, type_, 0, + adv_router, ls_seqnum, checksum, + length, opaque_type, opaque_id) @LSA.register_type(OSPF_OPAQUE_AS_LSA) -class ASOpaqueLSA(LSA): - pass +class ASOpaqueLSA(OpaqueLSA): + def __init__(self, ls_age=0, options=0, type_=OSPF_OPAQUE_AS_LSA, + adv_router='0.0.0.0', ls_seqnum=0, checksum=0, length=0, + opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, opaque_id=0, data=None): + self.data = data + super(ASOpaqueLSA, self).__init__(ls_age, options, type_, 0, + adv_router, ls_seqnum, checksum, + length, opaque_type, opaque_id) class OSPFMessage(packet_base.PacketBase, _TypeDisp): |