summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2014-07-02 18:16:52 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2014-07-03 00:09:23 +0900
commitf96435bcfa57d45e01d22aa96f8567545e26f6e7 (patch)
tree4ac182a2cc7a0d30846d30e6e178446a32ea52ec
parentfdce89a0def2b20d5dffda541207e2d482e2b652 (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.py109
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):