packet/zebra: Support FRRouting version 3.0

This patch enables to support Zebra messages of FRRouting version 3.0
and introduces a flag to switch FRRouting version.

Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
IWASE Yusuke 2017-10-17 14:20:51 +09:00 committed by FUJITA Tomonori
parent 6e51b2a41d
commit 66bdeaa7b5
4 changed files with 203 additions and 43 deletions

View File

@ -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

View File

@ -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')

View File

@ -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(

View File

@ -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)