summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-09-05 10:13:36 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-09-17 13:36:40 +0900
commita5f24fe3e32ba1f8e210e77917d8dd28ad9e96b9 (patch)
tree285412bd48acec42b983164b82c5269c9a7cd73f
parentb66c597fb659c314cd23c661193d160b73458b73 (diff)
packet/zebra: Support asymmetric structure of ZEBRA_*_IMPORT_LOOKUP
The ZEBRA_IPV4_IMPORT_LOOKUP/ZEBRA_IPV6_IMPORT_LOOKUP has asymmetric structures at when sent to Zebra daemon and when sent from Zebra daemon. Especially, "prefix_len" field is inserted before "prefix" filed when sent to Zebra daemon. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/packet/zebra.py80
1 files changed, 63 insertions, 17 deletions
diff --git a/ryu/lib/packet/zebra.py b/ryu/lib/packet/zebra.py
index 25c72391..62b4d8ff 100644
--- a/ryu/lib/packet/zebra.py
+++ b/ryu/lib/packet/zebra.py
@@ -1629,12 +1629,29 @@ class _ZebraIPImportLookup(_ZebraMessageBody):
"""
Base class for ZEBRA_IPV4_IMPORT_LOOKUP and
ZEBRA_IPV6_IMPORT_LOOKUP message body.
+
+ .. Note::
+
+ Zebra IPv4/v6 Import Lookup message have asymmetric structure.
+ If the message sent from Zebra Daemon, set 'from_zebra=True' to
+ create an instance of this class.
"""
- # Zebra IPv4/v6 Import Lookup message body:
+ # Zebra IPv4/v6 Import Lookup message body
+ # (Protocol Daemons -> Zebra Daemon):
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # | IPv4/v6 prefix |
+ # | Prefix Len |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | IPv4/v6 Prefix (4 bytes or 16 bytes) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Zebra IPv4/v6 Import Lookup message body
+ # (Zebra Daemons -> Protocol Daemon):
+ # 0 1 2 3
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | IPv4/v6 Prefix (4 bytes or 16 bytes) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Metric |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -1642,6 +1659,8 @@ class _ZebraIPImportLookup(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Nexthops (Variable) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ _PREFIX_LEN_FMT = '!B' # prefix_len
+ PREFIX_LEN_SIZE = struct.calcsize(_PREFIX_LEN_FMT)
_METRIC_FMT = '!I' # metric
METRIC_SIZE = struct.calcsize(_METRIC_FMT)
@@ -1649,37 +1668,64 @@ class _ZebraIPImportLookup(_ZebraMessageBody):
PREFIX_CLS = None # either addrconv.ipv4 or addrconv.ipv6
PREFIX_LEN = None # IP prefix length in bytes
- def __init__(self, prefix, metric=None, nexthops=None):
+ def __init__(self, prefix, metric=None, nexthops=None,
+ from_zebra=False):
super(_ZebraIPImportLookup, self).__init__()
- assert netaddr.valid_ipv4(prefix) or netaddr.valid_ipv6(prefix)
+ if not from_zebra:
+ assert ip.valid_ipv4(prefix) or ip.valid_ipv6(prefix)
+ else:
+ if isinstance(prefix, (IPv4Prefix, IPv6Prefix)):
+ prefix = prefix.prefix
+ else:
+ assert netaddr.valid_ipv4(prefix) or netaddr.valid_ipv6(prefix)
self.prefix = prefix
self.metric = metric
nexthops = nexthops or []
for nexthop in nexthops:
assert isinstance(nexthop, _NextHop)
self.nexthops = nexthops
+ self.from_zebra = from_zebra
@classmethod
- def parse(cls, buf, version=_DEFAULT_VERSION):
+ def parse_impl(cls, buf, version=_DEFAULT_VERSION, from_zebra=False):
+ if not from_zebra:
+ (prefix_len,) = struct.unpack_from(cls._PREFIX_LEN_FMT, buf)
+ rest = buf[cls.PREFIX_LEN_SIZE:]
+ prefix = cls.PREFIX_CLS.bin_to_text(rest[:cls.PREFIX_LEN])
+ return cls('%s/%d' % (prefix, prefix_len), from_zebra=False)
+
prefix = cls.PREFIX_CLS.bin_to_text(buf[:cls.PREFIX_LEN])
- rest = buf[cls.PREFIX_LEN:]
+ rest = buf[4:]
- metric = None
- if rest:
- (metric,) = struct.unpack_from(cls._METRIC_FMT, rest)
- rest = rest[cls.METRIC_SIZE:]
+ (metric,) = struct.unpack_from(cls._METRIC_FMT, rest)
+ rest = rest[cls.METRIC_SIZE:]
- nexthops = None
- if rest:
- nexthops, rest = _parse_nexthops(rest)
+ nexthops, rest = _parse_nexthops(rest)
+
+ return cls(prefix, metric, nexthops, from_zebra=True)
+
+ @classmethod
+ def parse(cls, buf, version=_DEFAULT_VERSION):
+ return cls.parse_impl(buf, version=version, from_zebra=False)
- return cls(prefix, metric, nexthops)
+ @classmethod
+ def parse_from_zebra(cls, buf, version=_DEFAULT_VERSION):
+ return cls.parse_impl(buf, version=version, from_zebra=True)
def serialize(self, version=_DEFAULT_VERSION):
- buf = self.PREFIX_CLS.text_to_bin(self.prefix)
+ if not self.from_zebra:
+ if ip.valid_ipv4(self.prefix) or ip.valid_ipv6(self.prefix):
+ prefix, prefix_len = self.prefix.split('/')
+ return struct.pack(
+ self._PREFIX_LEN_FMT,
+ int(prefix_len)) + self.PREFIX_CLS.text_to_bin(prefix)
+ else:
+ raise ValueError('Invalid prefix: %s' % self.prefix)
- if self.metric is None:
- return buf
+ if netaddr.valid_ipv4(self.prefix) or netaddr.valid_ipv6(self.prefix):
+ buf = self.PREFIX_CLS.text_to_bin(self.prefix)
+ else:
+ raise ValueError('Invalid prefix: %s' % self.prefix)
buf += struct.pack(self._METRIC_FMT, self.metric)