summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ryu/cfg.py1
-rw-r--r--ryu/flags.py8
-rw-r--r--ryu/lib/packet/zebra.py164
-rw-r--r--ryu/tests/unit/packet/test_zebra.py73
4 files changed, 203 insertions, 43 deletions
diff --git a/ryu/cfg.py b/ryu/cfg.py
index c917b0b5..d2951ee7 100644
--- a/ryu/cfg.py
+++ b/ryu/cfg.py
@@ -36,6 +36,7 @@ CONF = oslo_config.cfg.ConfigOpts()
from oslo_config.cfg import ConfigOpts
+from oslo_config.cfg import Opt
from oslo_config.cfg import BoolOpt
from oslo_config.cfg import IntOpt
from oslo_config.cfg import ListOpt
diff --git a/ryu/flags.py b/ryu/flags.py
index 69eb3d22..b63b9b5e 100644
--- a/ryu/flags.py
+++ b/ryu/flags.py
@@ -17,6 +17,8 @@
global flags
"""
+from distutils.version import LooseVersion
+
from ryu import cfg
CONF = cfg.CONF
@@ -80,6 +82,9 @@ DEFAULT_ZSERV_CLIENT_ROUTE_TYPE = 'BGP'
DEFAULT_ZSERV_INTERVAL = 10
DEFAULT_ZSERV_DATABASE = 'sqlite:///zebra.db'
DEFAULT_ZSERV_ROUTER_ID = '1.1.1.1'
+# For the backward compatibility with Quagga, the default FRRouting version
+# should be None.
+DEFAULT_ZSERV_FRR_VERSION = '0.0'
CONF.register_cli_opts([
cfg.StrOpt(
@@ -111,4 +116,7 @@ CONF.register_cli_opts([
'router-id', default=DEFAULT_ZSERV_ROUTER_ID,
help='Initial Router ID used by Zebra protocol service '
'(default: %s)' % DEFAULT_ZSERV_ROUTER_ID),
+ cfg.Opt(
+ 'frr-version', LooseVersion, default=DEFAULT_ZSERV_FRR_VERSION,
+ help='FRRouting version when integrated with FRRouting (e.g., 3.0)'),
], group='zapi')
diff --git a/ryu/lib/packet/zebra.py b/ryu/lib/packet/zebra.py
index 8e5b5129..ad8b4f07 100644
--- a/ryu/lib/packet/zebra.py
+++ b/ryu/lib/packet/zebra.py
@@ -23,10 +23,13 @@ import abc
import socket
import struct
import logging
+from distutils.version import LooseVersion
import netaddr
import six
+from ryu import flags as cfg_flags # For loading 'zapi' option definition
+from ryu.cfg import CONF
from ryu.lib import addrconv
from ryu.lib import ip
from ryu.lib import stringify
@@ -42,6 +45,9 @@ LOG = logging.getLogger(__name__)
_DEFAULT_VERSION = 3
_DEFAULT_FRR_VERSION = 4
+_FRR_VERSION_2_0 = LooseVersion('2.0')
+_FRR_VERSION_3_0 = LooseVersion('3.0')
+
# Constants in quagga/lib/zebra.h
# Default Zebra TCP port
@@ -462,6 +468,10 @@ def _serialize_zebra_family_prefix(prefix):
raise ValueError('Invalid prefix: %s' % prefix)
+def _is_frr_version_ge(compared_version):
+ return CONF['zapi'].frr_version >= compared_version
+
+
class InterfaceLinkParams(stringify.StringifyMixin):
"""
Interface Link Parameters class for if_link_params structure.
@@ -733,15 +743,27 @@ class NextHopIPv4(_NextHop):
"""
_BODY_FMT = '!4s' # addr(IPv4)
BODY_SIZE = struct.calcsize(_BODY_FMT)
+ _BODY_FMT_FRR_V3 = '!4sI' # addr(IPv4), ifindex
+ BODY_SIZE_FRR_V3 = struct.calcsize(_BODY_FMT_FRR_V3)
@classmethod
def parse(cls, buf):
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ (addr, ifindex) = struct.unpack_from(cls._BODY_FMT_FRR_V3, buf)
+ addr = addrconv.ipv4.bin_to_text(addr)
+ rest = buf[cls.BODY_SIZE_FRR_V3:]
+ return cls(ifindex=ifindex, addr=addr), rest
+
addr = addrconv.ipv4.bin_to_text(buf[:cls.BODY_SIZE])
rest = buf[cls.BODY_SIZE:]
return cls(addr=addr), rest
def _serialize(self):
+ if _is_frr_version_ge(_FRR_VERSION_3_0) and self.ifindex:
+ addr = addrconv.ipv4.text_to_bin(self.addr)
+ return struct.pack(self._BODY_FMT_FRR_V3, addr, self.ifindex)
+
return addrconv.ipv4.text_to_bin(self.addr)
@@ -798,15 +820,27 @@ class NextHopIPv6(_NextHop):
"""
_BODY_FMT = '!16s' # addr(IPv6)
BODY_SIZE = struct.calcsize(_BODY_FMT)
+ _BODY_FMT_FRR_V3 = '!16sI' # addr(IPv6), ifindex
+ BODY_SIZE_FRR_V3 = struct.calcsize(_BODY_FMT_FRR_V3)
@classmethod
def parse(cls, buf):
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ (addr, ifindex) = struct.unpack_from(cls._BODY_FMT_FRR_V3, buf)
+ addr = addrconv.ipv4.bin_to_text(addr)
+ rest = buf[cls.BODY_SIZE_FRR_V3:]
+ return cls(ifindex=ifindex, addr=addr), rest
+
addr = addrconv.ipv6.bin_to_text(buf[:cls.BODY_SIZE])
rest = buf[cls.BODY_SIZE:]
return cls(addr=addr), rest
def _serialize(self):
+ if _is_frr_version_ge(_FRR_VERSION_3_0) and self.ifindex:
+ addr = addrconv.ipv4.text_to_bin(self.addr)
+ return struct.pack(self._BODY_FMT_FRR_V3, addr, self.ifindex)
+
return addrconv.ipv6.text_to_bin(self.addr)
@@ -1226,6 +1260,8 @@ class _ZebraInterface(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Metric |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | (Speed): v4(FRRouting v3.0 or later) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Interface's MTU for IPv4 |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Interface's MTU for IPv6 |
@@ -1254,8 +1290,12 @@ class _ZebraInterface(_ZebraMessageBody):
V3_HEADER_SIZE = struct.calcsize(_V3_HEADER_FMT)
# ifname, ifindex, status, if_flags, ptm_enable, ptm_status, metric,
# ifmtu, ifmtu6, bandwidth, ll_type, hw_addr_len
- _V4_HEADER_FMT = '!%dsIBQBBIIIIII' % INTERFACE_NAMSIZE
- V4_HEADER_SIZE = struct.calcsize(_V4_HEADER_FMT)
+ _V4_HEADER_FMT_2_0 = '!%dsIBQBBIIIIII' % INTERFACE_NAMSIZE
+ V4_HEADER_SIZE_2_0 = struct.calcsize(_V4_HEADER_FMT_2_0)
+ # ifname, ifindex, status, if_flags, ptm_enable, ptm_status, metric,
+ # speed, ifmtu, ifmtu6, bandwidth, ll_type, hw_addr_len
+ _V4_HEADER_FMT_3_0 = '!%dsIBQBBIIIIIII' % INTERFACE_NAMSIZE
+ V4_HEADER_SIZE_3_0 = struct.calcsize(_V4_HEADER_FMT_3_0)
# link_params_state (whether a link-params follows)
_LP_STATE_FMT = '!?'
@@ -1264,8 +1304,8 @@ class _ZebraInterface(_ZebraMessageBody):
def __init__(self, ifname=None, ifindex=None, status=None, if_flags=None,
ptm_enable=None, ptm_status=None,
- metric=None, ifmtu=None, ifmtu6=None, bandwidth=None,
- ll_type=None, hw_addr_len=0, hw_addr=None,
+ metric=None, speed=None, ifmtu=None, ifmtu6=None,
+ bandwidth=None, ll_type=None, hw_addr_len=0, hw_addr=None,
link_params=None):
super(_ZebraInterface, self).__init__()
self.ifname = ifname
@@ -1275,6 +1315,7 @@ class _ZebraInterface(_ZebraMessageBody):
self.ptm_enable = ptm_enable
self.ptm_status = ptm_status
self.metric = metric
+ self.speed = speed
self.ifmtu = ifmtu
self.ifmtu6 = ifmtu6
self.bandwidth = bandwidth
@@ -1290,6 +1331,7 @@ class _ZebraInterface(_ZebraMessageBody):
def parse(cls, buf, version=_DEFAULT_VERSION):
ptm_enable = None
ptm_status = None
+ speed = None
ll_type = None
if version <= 2:
(ifname, ifindex, status, if_flags, metric,
@@ -1302,10 +1344,20 @@ class _ZebraInterface(_ZebraMessageBody):
hw_addr_len) = struct.unpack_from(cls._V3_HEADER_FMT, buf)
rest = buf[cls.V3_HEADER_SIZE:]
elif version == 4:
- (ifname, ifindex, status, if_flags, ptm_enable, ptm_status,
- metric, ifmtu, ifmtu6, bandwidth, ll_type,
- hw_addr_len) = struct.unpack_from(cls._V4_HEADER_FMT, buf)
- rest = buf[cls.V4_HEADER_SIZE:]
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ (ifname, ifindex, status, if_flags, ptm_enable, ptm_status,
+ metric, speed, ifmtu, ifmtu6, bandwidth, ll_type,
+ hw_addr_len) = struct.unpack_from(cls._V4_HEADER_FMT_3_0, buf)
+ rest = buf[cls.V4_HEADER_SIZE_3_0:]
+ elif _is_frr_version_ge(_FRR_VERSION_2_0):
+ (ifname, ifindex, status, if_flags, ptm_enable, ptm_status,
+ metric, ifmtu, ifmtu6, bandwidth, ll_type,
+ hw_addr_len) = struct.unpack_from(cls._V4_HEADER_FMT_2_0, buf)
+ rest = buf[cls.V4_HEADER_SIZE_2_0:]
+ else:
+ raise struct.error(
+ 'Unsupported FRRouting version: %s'
+ % CONF['zapi'].frr_version)
else:
raise struct.error(
'Unsupported Zebra protocol version: %d'
@@ -1325,7 +1377,7 @@ class _ZebraInterface(_ZebraMessageBody):
if not rest:
return cls(ifname, ifindex, status, if_flags,
- ptm_enable, ptm_status, metric, ifmtu, ifmtu6,
+ ptm_enable, ptm_status, metric, speed, ifmtu, ifmtu6,
bandwidth, ll_type, hw_addr_len, hw_addr)
(link_param_state,) = struct.unpack_from(cls._LP_STATE_FMT, rest)
@@ -1337,7 +1389,7 @@ class _ZebraInterface(_ZebraMessageBody):
link_params = None
return cls(ifname, ifindex, status, if_flags,
- ptm_enable, ptm_status, metric, ifmtu, ifmtu6,
+ ptm_enable, ptm_status, metric, speed, ifmtu, ifmtu6,
bandwidth, ll_type, hw_addr_len, hw_addr,
link_params)
@@ -1368,12 +1420,24 @@ class _ZebraInterface(_ZebraMessageBody):
self.if_flags, self.metric, self.ifmtu, self.ifmtu6,
self.bandwidth, self.ll_type, hw_addr_len) + hw_addr
elif version == 4:
- buf = struct.pack(
- self._V4_HEADER_FMT,
- self.ifname.encode('ascii'), self.ifindex, self.status,
- self.if_flags, self.ptm_enable, self.ptm_status, self.metric,
- self.ifmtu, self.ifmtu6,
- self.bandwidth, self.ll_type, hw_addr_len) + hw_addr
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ buf = struct.pack(
+ self._V4_HEADER_FMT_3_0,
+ self.ifname.encode('ascii'), self.ifindex, self.status,
+ self.if_flags, self.ptm_enable, self.ptm_status,
+ self.metric, self.speed, self.ifmtu, self.ifmtu6,
+ self.bandwidth, self.ll_type, hw_addr_len) + hw_addr
+ elif _is_frr_version_ge(_FRR_VERSION_2_0):
+ buf = struct.pack(
+ self._V4_HEADER_FMT_2_0,
+ self.ifname.encode('ascii'), self.ifindex, self.status,
+ self.if_flags, self.ptm_enable, self.ptm_status,
+ self.metric, self.ifmtu, self.ifmtu6,
+ self.bandwidth, self.ll_type, hw_addr_len) + hw_addr
+ else:
+ raise ValueError(
+ 'Unsupported FRRouting version: %s'
+ % CONF['zapi'].frr_version)
else:
raise ValueError(
'Unsupported Zebra protocol version: %d'
@@ -1552,6 +1616,8 @@ class _ZebraIPRoute(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | IPv4/v6 Prefix (Variable) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | (IPv4/v6 Source Prefix): v4(FRRouting v3.0 or later) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Nexthop Num |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Nexthops (Variable) |
@@ -1603,6 +1669,8 @@ class _ZebraIPRoute(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | IPv4/v6 Prefix (Variable) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | (IPv4/v6 Source Prefix): v4(FRRouting v3.0 or later) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | (Nexthop Num) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | (Nexthops (Variable)) |
@@ -1631,7 +1699,8 @@ class _ZebraIPRoute(_ZebraMessageBody):
# API type specific constants
_FAMILY = None # either socket.AF_INET or socket.AF_INET6
- def __init__(self, route_type, flags, message, safi=None, prefix=None,
+ def __init__(self, route_type, flags, message, safi=None,
+ prefix=None, src_prefix=None,
nexthops=None, ifindexes=None,
distance=None, metric=None, mtu=None, tag=None,
instance=None, from_zebra=False):
@@ -1652,6 +1721,10 @@ class _ZebraIPRoute(_ZebraMessageBody):
prefix = prefix.prefix
self.prefix = prefix
+ if isinstance(src_prefix, (IPv4Prefix, IPv6Prefix)):
+ src_prefix = src_prefix.prefix
+ self.src_prefix = src_prefix
+
# Nexthops should be a list of str representations of IP address
# if this message sent from Zebra, otherwise a list of _Nexthop
# subclasses.
@@ -1715,6 +1788,10 @@ class _ZebraIPRoute(_ZebraMessageBody):
prefix, rest = _parse_ip_prefix(cls._FAMILY, rest)
+ src_prefix = None
+ if version == 4 and message & FRR_ZAPI_MESSAGE_SRCPFX:
+ src_prefix, rest = _parse_ip_prefix(cls._FAMILY, rest)
+
if from_zebra and message & ZAPI_MESSAGE_NEXTHOP:
nexthops = []
(nexthop_num,) = struct.unpack_from(cls._NUM_FMT, rest)
@@ -1764,7 +1841,7 @@ class _ZebraIPRoute(_ZebraMessageBody):
'Unsupported Zebra protocol version: %d'
% version)
- return cls(route_type, flags, message, safi, prefix,
+ return cls(route_type, flags, message, safi, prefix, src_prefix,
nexthops, ifindexes,
distance, metric, mtu, tag,
instance, from_zebra=from_zebra)
@@ -1788,6 +1865,9 @@ class _ZebraIPRoute(_ZebraMessageBody):
def serialize(self, version=_DEFAULT_VERSION):
prefix = _serialize_ip_prefix(self.prefix)
+ if version == 4 and self.src_prefix:
+ self.message |= FRR_ZAPI_MESSAGE_SRCPFX # fixup
+ prefix += _serialize_ip_prefix(self.src_prefix)
nexthops = b''
if self.from_zebra and self.nexthops:
@@ -2491,6 +2571,8 @@ class ZebraNexthopUpdate(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | IPv4/v6 prefix |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | (Distance) | v4(FRRouting v3.0 or later)
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Metric |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Nexthop Num |
@@ -2499,15 +2581,22 @@ class ZebraNexthopUpdate(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
_FAMILY_FMT = '!H' # family
FAMILY_SIZE = struct.calcsize(_FAMILY_FMT)
+ _DISTANCE_FMT = '!B' # metric
+ DISTANCE_SIZE = struct.calcsize(_DISTANCE_FMT)
_METRIC_FMT = '!I' # metric
METRIC_SIZE = struct.calcsize(_METRIC_FMT)
- def __init__(self, family, prefix, metric, nexthops=None):
+ def __init__(self, family, prefix, distance=None, metric=None,
+ nexthops=None):
super(ZebraNexthopUpdate, self).__init__()
self.family = family
if isinstance(prefix, (IPv4Prefix, IPv6Prefix)):
prefix = prefix.prefix
self.prefix = prefix
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ assert distance is not None
+ self.distance = distance
+ assert metric is not None
self.metric = metric
nexthops = nexthops or []
for nexthop in nexthops:
@@ -2521,12 +2610,17 @@ class ZebraNexthopUpdate(_ZebraMessageBody):
prefix, rest = _parse_ip_prefix(family, rest)
+ distance = None
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ (distance,) = struct.unpack_from(cls._DISTANCE_FMT, rest)
+ rest = rest[cls.DISTANCE_SIZE:]
+
(metric,) = struct.unpack_from(cls._METRIC_FMT, rest)
rest = rest[cls.METRIC_SIZE:]
nexthops, rest = _parse_nexthops(rest, version)
- return cls(family, prefix, metric, nexthops)
+ return cls(family, prefix, distance, metric, nexthops)
def serialize(self, version=_DEFAULT_VERSION):
# fixup
@@ -2541,6 +2635,9 @@ class ZebraNexthopUpdate(_ZebraMessageBody):
buf += _serialize_ip_prefix(self.prefix)
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ buf += struct.pack(self._DISTANCE_FMT, self.distance)
+
buf += struct.pack(self._METRIC_FMT, self.metric)
return buf + _serialize_nexthops(self.nexthops, version=version)
@@ -3200,6 +3297,8 @@ class _ZebraMplsLabels(_ZebraMessageBody):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Gate IPv4/v6 Address (4 bytes/16 bytes) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Interface Index: v4(FRRouting v3.0 or later) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Distance |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | In Label |
@@ -3216,10 +3315,12 @@ class _ZebraMplsLabels(_ZebraMessageBody):
IPV6_PREFIX_SIZE = struct.calcsize(_IPV6_PREFIX_FMT)
_FAMILY_IPV4_PREFIX_FMT = '!I4sB'
_FAMILY_IPV6_PREFIX_FMT = '!I16sB'
+ _IFINDEX_FMT = '!I'
+ IFINDEX_SIZE = struct.calcsize(_IFINDEX_FMT)
_BODY_FMT = '!BII' # distance, in_label, out_label
- def __init__(self, route_type, family, prefix, gate_addr,
- distance, in_label, out_label):
+ def __init__(self, route_type, family, prefix, gate_addr, ifindex=None,
+ distance=None, in_label=None, out_label=None):
super(_ZebraMplsLabels, self).__init__()
self.route_type = route_type
self.family = family
@@ -3228,8 +3329,14 @@ class _ZebraMplsLabels(_ZebraMessageBody):
self.prefix = prefix
assert netaddr.valid_ipv4(gate_addr) or netaddr.valid_ipv6(gate_addr)
self.gate_addr = gate_addr
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ assert ifindex is not None
+ self.ifindex = ifindex
+ assert distance is not None
self.distance = distance
+ assert in_label is not None
self.in_label = in_label
+ assert out_label is not None
self.out_label = out_label
@classmethod
@@ -3266,10 +3373,15 @@ class _ZebraMplsLabels(_ZebraMessageBody):
else:
raise struct.error('Unsupported family: %d' % family)
+ ifindex = None
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ (ifindex,) = struct.unpack_from(cls._IFINDEX_FMT, rest)
+ rest = rest[cls.IFINDEX_SIZE:]
+
(distance, in_label,
out_label) = struct.unpack_from(cls._BODY_FMT, rest)
- return cls(route_type, family, prefix, gate_addr,
+ return cls(route_type, family, prefix, gate_addr, ifindex,
distance, in_label, out_label)
def _serialize_family_prefix(self, prefix):
@@ -3303,7 +3415,11 @@ class _ZebraMplsLabels(_ZebraMessageBody):
else:
raise ValueError('Unsupported family: %d' % self.family)
- body_bin = struct.pack(
+ body_bin = b''
+ if _is_frr_version_ge(_FRR_VERSION_3_0):
+ body_bin = struct.pack(self._IFINDEX_FMT, self.ifindex)
+
+ body_bin += struct.pack(
self._BODY_FMT, self.distance, self.in_label, self.out_label)
return struct.pack(
diff --git a/ryu/tests/unit/packet/test_zebra.py b/ryu/tests/unit/packet/test_zebra.py
index b5fb9c5d..4ea76b55 100644
--- a/ryu/tests/unit/packet/test_zebra.py
+++ b/ryu/tests/unit/packet/test_zebra.py
@@ -15,6 +15,11 @@
from __future__ import print_function
+try:
+ import mock # Python 2
+except ImportError:
+ from unittest import mock # Python 3
+
import os
import socket
import sys
@@ -36,37 +41,53 @@ PCAP_DATA_DIR = os.path.join(
'../../packet_data/pcap/')
+_patch_frr_v2 = mock.patch(
+ 'ryu.lib.packet.zebra._is_frr_version_ge',
+ mock.MagicMock(side_effect=lambda x: x == zebra._FRR_VERSION_2_0))
+
+
class Test_zebra(unittest.TestCase):
"""
Test case for ryu.lib.packet.zebra.
"""
- def test_pcap(self):
+ @staticmethod
+ def _test_pcap_single(f):
+ zebra_pcap_file = os.path.join(PCAP_DATA_DIR, f + '.pcap')
+ # print('*** testing %s' % zebra_pcap_file)
+
+ for _, buf in pcaplib.Reader(open(zebra_pcap_file, 'rb')):
+ # Checks if Zebra message can be parsed as expected.
+ pkt = packet.Packet(buf)
+ zebra_pkts = pkt.get_protocols(zebra.ZebraMessage)
+ for zebra_pkt in zebra_pkts:
+ ok_(isinstance(zebra_pkt, zebra.ZebraMessage),
+ 'Failed to parse Zebra message: %s' % pkt)
+ ok_(not isinstance(pkt.protocols[-1],
+ (six.binary_type, bytearray)),
+ 'Some messages could not be parsed in %s: %s' % (f, pkt))
+
+ # Checks if Zebra message can be serialized as expected.
+ pkt.serialize()
+ eq_(binary_str(buf), binary_str(pkt.data))
+
+ def test_pcap_quagga(self):
files = [
'zebra_v2',
'zebra_v3',
+ ]
+
+ for f in files:
+ self._test_pcap_single(f)
+
+ @_patch_frr_v2
+ def test_pcap_frr_v2(self):
+ files = [
'zebra_v4_frr_v2', # API version 4 on FRRouting v2.0
]
for f in files:
- zebra_pcap_file = os.path.join(PCAP_DATA_DIR, f + '.pcap')
- # print('*** testing %s' % zebra_pcap_file)
-
- for _, buf in pcaplib.Reader(open(zebra_pcap_file, 'rb')):
- # Checks if Zebra message can be parsed as expected.
- pkt = packet.Packet(buf)
- zebra_pkts = pkt.get_protocols(zebra.ZebraMessage)
- for zebra_pkt in zebra_pkts:
- ok_(isinstance(zebra_pkt, zebra.ZebraMessage),
- 'Failed to parse Zebra message: %s' % pkt)
- ok_(not isinstance(pkt.protocols[-1],
- (six.binary_type, bytearray)),
- 'Some messages could not be parsed: %s' % pkt)
-
- # Checks if Zebra message can be serialized as expected.
- pkt.serialize()
- eq_(buf, pkt.data,
- "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))
+ self._test_pcap_single(f)
class TestZebraMessage(unittest.TestCase):
@@ -227,6 +248,7 @@ class TestZebraNexthopUpdateIPv6(unittest.TestCase):
nexthop_type = zebra.ZEBRA_NEXTHOP_IFINDEX
ifindex = 2
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraNexthopUpdate.parse(self.buf)
@@ -253,6 +275,7 @@ class TestZebraInterfaceNbrAddressAdd(unittest.TestCase):
family = socket.AF_INET
prefix = '192.168.1.0/24'
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraInterfaceNbrAddressAdd.parse(self.buf)
@@ -283,6 +306,7 @@ class TestZebraInterfaceBfdDestinationUpdate(unittest.TestCase):
src_family = socket.AF_INET
src_prefix = '192.168.1.2/24'
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraInterfaceBfdDestinationUpdate.parse(self.buf)
@@ -323,6 +347,7 @@ class TestZebraBfdDestinationRegisterMultiHopEnabled(unittest.TestCase):
multi_hop_count = 5
ifname = None
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraBfdDestinationRegister.parse(self.buf)
@@ -369,6 +394,7 @@ class TestZebraBfdDestinationRegisterMultiHopDisabled(unittest.TestCase):
multi_hop_count = None
ifname = 'eth0'
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraBfdDestinationRegister.parse(self.buf)
@@ -420,6 +446,7 @@ class TestZebraBfdDestinationRegisterMultiHopEnabledIPv6(unittest.TestCase):
multi_hop_count = 5
ifname = None
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraBfdDestinationRegister.parse(self.buf)
@@ -459,6 +486,7 @@ class TestZebraBfdDestinationDeregisterMultiHopEnabled(unittest.TestCase):
multi_hop_count = 5
ifname = None
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraBfdDestinationDeregister.parse(self.buf)
@@ -496,6 +524,7 @@ class TestZebraBfdDestinationDeregisterMultiHopDisabled(unittest.TestCase):
multi_hop_count = None
ifname = 'eth0'
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraBfdDestinationDeregister.parse(self.buf)
@@ -538,6 +567,7 @@ class TestZebraBfdDestinationDeregisterMultiHopEnabledIPv6(unittest.TestCase):
multi_hop_count = 5
ifname = None
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraBfdDestinationDeregister.parse(self.buf)
@@ -569,6 +599,7 @@ class TestZebraVrfAdd(unittest.TestCase):
)
vrf_name = 'VRF1'
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraVrfAdd.parse(self.buf)
@@ -587,6 +618,7 @@ class TestZebraInterfaceVrfUpdate(unittest.TestCase):
ifindex = 1
vrf_id = 2
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraInterfaceVrfUpdate.parse(self.buf)
@@ -606,6 +638,7 @@ class TestZebraInterfaceEnableRadv(unittest.TestCase):
ifindex = 1
interval = 0x100
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraInterfaceEnableRadv.parse(self.buf)
@@ -636,6 +669,7 @@ class TestZebraMplsLabelsAddIPv4(unittest.TestCase):
in_label = 100
out_label = zebra.MPLS_IMP_NULL_LABEL
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraMplsLabelsAdd.parse(self.buf)
@@ -677,6 +711,7 @@ class TestZebraMplsLabelsAddIPv6(unittest.TestCase):
in_label = 100
out_label = zebra.MPLS_IMP_NULL_LABEL
+ @_patch_frr_v2
def test_parser(self):
body = zebra.ZebraMplsLabelsAdd.parse(self.buf)