// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/fea/libfeaclient_bridge.cc,v 1.18 2007/02/16 22:45:45 pavlin Exp $"
#include "fea_module.h"
#include "libxorp/xorp.h"
#include "libxorp/xlog.h"
#include "libxorp/debug.h"
#include "libxipc/xrl_router.hh"
#include "libfeaclient/ifmgr_atoms.hh"
#include "libfeaclient/ifmgr_cmds.hh"
#include "libfeaclient/ifmgr_xrl_replicator.hh"
#include "libfeaclient_bridge.hh"
// ----------------------------------------------------------------------------
// Debug helpers
static const char*
update_name(IfConfigUpdateReporterBase::Update u)
{
switch (u) {
case IfConfigUpdateReporterBase::CREATED:
return "Creation";
case IfConfigUpdateReporterBase::DELETED:
return "Deletion";
case IfConfigUpdateReporterBase::CHANGED:
break; // FALLTHROUGH
}
return "Change";
}
static const char*
truth_of(bool v)
{
return v ? "true" : "false";
}
// ----------------------------------------------------------------------------
// LibFeaClientBridge implementation
LibFeaClientBridge::LibFeaClientBridge(XrlRouter& rtr)
: _iftree(0)
{
_rm = new IfMgrXrlReplicationManager(rtr);
}
LibFeaClientBridge::~LibFeaClientBridge()
{
delete _rm;
}
void
LibFeaClientBridge::set_iftree(const IfTree* tree)
{
_iftree = tree;
}
bool
LibFeaClientBridge::add_libfeaclient_mirror(const string& m)
{
return _rm->add_mirror(m);
}
bool
LibFeaClientBridge::remove_libfeaclient_mirror(const string& m)
{
return _rm->remove_mirror(m);
}
const IfMgrIfTree&
LibFeaClientBridge::libfeaclient_iftree() const
{
return _rm->iftree();
}
const IfTree*
LibFeaClientBridge::fea_iftree() const
{
return _iftree;
}
void
LibFeaClientBridge::interface_update(const string& ifname,
const Update& update,
bool system)
{
debug_msg("%s update for interface %s (system = %s)\n",
update_name(update), ifname.c_str(), truth_of(system));
if (system) {
//
// XXX: We don't propagate interface-related changes that just
// appear beneath us within the system. I.e., all changes
// should be through the FEA.
//
return;
}
XLOG_ASSERT(_iftree != 0);
switch (update) {
case CREATED:
_rm->push(new IfMgrIfAdd(ifname));
break; // FALLTHROUGH
case DELETED:
_rm->push(new IfMgrIfRemove(ifname));
return;
case CHANGED:
break; // FALLTHROUGH
}
//
// Validate interface is in the FEA iftree we're using and
// in libfeaclient's equivalent.
//
const IfMgrIfAtom* ifa = _rm->iftree().find_if(ifname);
if (ifa == 0) {
XLOG_WARNING("Got update for interface not in libfeaclient tree: "
"%s\n", ifname.c_str());
return;
}
IfTree::IfMap::const_iterator ii = _iftree->get_if(ifname);
if (ii == _iftree->ifs().end()) {
XLOG_WARNING("Got update for interface not in FEA tree: %s\n",
ifname.c_str());
return;
}
//
// Copy interface state out of FEA iftree into libfeaclient's
// equivalent.
//
_rm->push(new IfMgrIfSetEnabled(ifname, ii->second.enabled()));
_rm->push(new IfMgrIfSetDiscard(ifname, ii->second.discard()));
_rm->push(new IfMgrIfSetMtu(ifname, ii->second.mtu()));
_rm->push(new IfMgrIfSetMac(ifname, ii->second.mac()));
_rm->push(new IfMgrIfSetPifIndex(ifname, ii->second.pif_index()));
_rm->push(new IfMgrIfSetNoCarrier(ifname, ii->second.no_carrier()));
//
// XXX TODO / TBD if need doing...
// _rm->push(new IfMgrIfSetIfFlags(ifname, ii- if_flags - relevant ????
//
}
void
LibFeaClientBridge::vif_update(const string& ifname,
const string& vifname,
const Update& update,
bool system)
{
debug_msg("%s update for vif %s/%s (system = %s)\n",
update_name(update), ifname.c_str(), vifname.c_str(),
truth_of(system));
if (system) {
//
// XXX: We don't propagate interface-related changes that just
// appear beneath us within the system. I.e., all changes
// should be through the FEA.
//
return;
}
XLOG_ASSERT(_iftree != 0);
switch (update) {
case CREATED:
_rm->push(new IfMgrVifAdd(ifname, vifname));
break; // FALLTHROUGH
case DELETED:
_rm->push(new IfMgrVifRemove(ifname, vifname));
return;
case CHANGED:
break; // FALLTHROUGH
}
//
// Validate vif is in the FEA iftree we're using and in
// libfeaclient's equivalent.
//
const IfMgrVifAtom* ifa = _rm->iftree().find_vif(ifname, vifname);
if (ifa == 0) {
XLOG_WARNING("Got update for vif not in libfeaclient tree: %s/%s",
ifname.c_str(), vifname.c_str());
return;
}
IfTree::IfMap::const_iterator ii = _iftree->get_if(ifname);
if (ii == _iftree->ifs().end()) {
XLOG_WARNING("Got update for vif on interface not in tree:"
"%s/(%s)", ifname.c_str(), vifname.c_str());
return;
}
const IfTreeInterface& iface = ii->second;
IfTreeInterface::VifMap::const_iterator vi = iface.get_vif(vifname);
if (vi == iface.vifs().end()) {
XLOG_WARNING("Got update for vif not in FEA tree: %s/%s",
ifname.c_str(), vifname.c_str());
return;
}
//
// Copy vif state out of FEA iftree into libfeaclient's
// equivalent.
//
const IfTreeVif& vif = vi->second;
_rm->push(new
IfMgrVifSetEnabled(ifname, vifname, vif.enabled())
);
_rm->push(new
IfMgrVifSetBroadcastCapable(ifname, vifname, vif.broadcast())
);
_rm->push(new
IfMgrVifSetLoopbackCapable(ifname, vifname, vif.loopback())
);
_rm->push(new
IfMgrVifSetP2PCapable(ifname, vifname, vif.point_to_point())
);
_rm->push(new
IfMgrVifSetMulticastCapable(ifname, vifname, vif.multicast())
);
_rm->push(new
IfMgrVifSetPifIndex(ifname, vifname, vif.pif_index())
);
}
void
LibFeaClientBridge::vifaddr4_update(const string& ifname,
const string& vifname,
const IPv4& addr,
const Update& update,
bool system)
{
debug_msg("%s update for address %s/%s/%s (system = %s)\n",
update_name(update), ifname.c_str(), vifname.c_str(),
addr.str().c_str(), truth_of(system));
if (system) {
//
// XXX: We don't propagate interface-related changes that just
// appear beneath us within the system. I.e., all changes
// should be through the FEA.
//
return;
}
XLOG_ASSERT(_iftree != 0);
switch (update) {
case CREATED:
_rm->push(new IfMgrIPv4Add(ifname, vifname, addr));
break; // FALLTHROUGH
case DELETED:
_rm->push(new IfMgrIPv4Remove(ifname, vifname, addr));
return;
case CHANGED:
break; // FALLTHROUGH
}
//
// Validate vif address is in the FEA iftree we're using and in
// libfeaclient's equivalent
//
const IfMgrIPv4Atom* ifa = _rm->iftree().find_addr(ifname,
vifname,
addr);
if (ifa == 0) {
XLOG_WARNING("Got update for address no in libfeaclient tree: "
"%s/%s/%s",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
IfTree::IfMap::const_iterator ii = _iftree->get_if(ifname);
if (ii == _iftree->ifs().end()) {
XLOG_WARNING("Got update for address on interface not in tree: "
"%s/(%s/%s)",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
const IfTreeInterface& iface = ii->second;
IfTreeInterface::VifMap::const_iterator vi = iface.get_vif(vifname);
if (vi == iface.vifs().end()) {
XLOG_WARNING("Got update for address on vif not in FEA tree: "
"%s/%s/(%s)",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
const IfTreeVif& vif = vi->second;
IfTreeVif::V4Map::const_iterator ai = vif.get_addr(addr);
if (ai == vif.v4addrs().end()) {
XLOG_WARNING("Got update for address not in FEA tree: %s/%s/%s",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
const IfTreeAddr4& a4 = ai->second;
//
// Copy address state out of FEA iftree into libfeaclient's
// equivalent.
//
_rm->push(new
IfMgrIPv4SetEnabled(ifname, vifname, addr, a4.enabled())
);
_rm->push(new
IfMgrIPv4SetLoopback(ifname, vifname, addr, a4.loopback())
);
_rm->push(new
IfMgrIPv4SetMulticastCapable(ifname, vifname, addr,
a4.multicast())
);
_rm->push(new
IfMgrIPv4SetPrefix(ifname, vifname, addr, a4.prefix_len())
);
if (a4.point_to_point()) {
const IPv4& end = a4.endpoint();
_rm->push(new IfMgrIPv4SetEndpoint(ifname, vifname, addr, end));
} else {
// NB if IfTreeAddr4::bcast() will return IPv4::ZERO() if
// broadcast is not supported. This happens to be the
// correct argument for libfeaclient to signify broadcast
// is not supported.
const IPv4& bcast = a4.bcast();
_rm->push(new IfMgrIPv4SetBroadcast(ifname, vifname, addr, bcast));
}
}
void
LibFeaClientBridge::vifaddr6_update(const string& ifname,
const string& vifname,
const IPv6& addr,
const Update& update,
bool system)
{
debug_msg("%s update for address %s/%s/%s (system = %s)\n",
update_name(update), ifname.c_str(), vifname.c_str(),
addr.str().c_str(), truth_of(system));
if (system) {
//
// XXX: We don't propagate interface-related changes that just
// appear beneath us within the system. I.e., all changes
// should be through the FEA.
//
return;
}
XLOG_ASSERT(_iftree != 0);
switch (update) {
case CREATED:
_rm->push(new IfMgrIPv6Add(ifname, vifname, addr));
break; // FALLTHROUGH
case DELETED:
_rm->push(new IfMgrIPv6Remove(ifname, vifname, addr));
return;
case CHANGED:
break; // FALLTHROUGH
}
//
// Validate vif address is in the FEA iftree we're using and in
// libfeaclient's equivalent
//
const IfMgrIPv6Atom* ifa = _rm->iftree().find_addr(ifname,
vifname,
addr);
if (ifa == 0) {
XLOG_WARNING("Got update for address no in libfeaclient tree: "
"%s/%s/%s",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
IfTree::IfMap::const_iterator ii = _iftree->get_if(ifname);
if (ii == _iftree->ifs().end()) {
XLOG_WARNING("Got update for address on interface not in tree: "
"%s/(%s/%s)",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
const IfTreeInterface& iface = ii->second;
IfTreeInterface::VifMap::const_iterator vi = iface.get_vif(vifname);
if (vi == iface.vifs().end()) {
XLOG_WARNING("Got update for address on vif not in FEA tree: "
"%s/%s/(%s)",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
const IfTreeVif& vif = vi->second;
IfTreeVif::V6Map::const_iterator ai = vif.get_addr(addr);
if (ai == vif.v6addrs().end()) {
XLOG_WARNING("Got update for address not in FEA tree: %s/%s/%s",
ifname.c_str(), vifname.c_str(), addr.str().c_str());
return;
}
const IfTreeAddr6& a6 = ai->second;
//
// Copy address state out of FEA iftree into libfeaclient's
// equivalent.
//
_rm->push(new
IfMgrIPv6SetEnabled(ifname, vifname, addr, a6.enabled())
);
_rm->push(new
IfMgrIPv6SetLoopback(ifname, vifname, addr, a6.loopback())
);
_rm->push(new
IfMgrIPv6SetMulticastCapable(ifname, vifname, addr,
a6.multicast())
);
_rm->push(new
IfMgrIPv6SetPrefix(ifname, vifname, addr, a6.prefix_len())
);
_rm->push(new
IfMgrIPv6SetEndpoint(ifname, vifname, addr, a6.endpoint()));
}
void
LibFeaClientBridge::updates_completed(bool system)
{
debug_msg("Updates completed (system = %s)\n", truth_of(system));
if (system) {
//
// XXX: We don't propagate interface-related changes that just
// appear beneath us within the system. I.e., all changes
// should be through the FEA.
//
return;
}
XLOG_ASSERT(_iftree != 0);
_rm->push(new IfMgrHintUpdatesMade());
}
// ----------------------------------------------------------------------------
// Sanity check / verification code (expensive)
#include <algorithm>
class AppendFeaIfNames {
public:
AppendFeaIfNames(string& out) : _out(out)
{}
void
operator() (const IfTree::IfMap::value_type& v)
{
_out += v.first + " ";
}
private:
string& _out;
};
class AppendFeaVifNames {
public:
AppendFeaVifNames(string& out) : _out(out)
{}
void
operator() (const IfTreeInterface::VifMap::value_type& v)
{
_out += v.first + " ";
}
private:
string& _out;
};
class AppendFeaV4Addrs {
public:
AppendFeaV4Addrs(string& out) : _out(out)
{}
void
operator() (const IfTreeVif::V4Map::value_type& v)
{
_out += v.first.str() + " ";
}
private:
string& _out;
};
class AppendFeaV6Addrs {
public:
AppendFeaV6Addrs(string& out) : _out(out)
{}
void
operator() (const IfTreeVif::V6Map::value_type& v)
{
_out += v.first.str() + " ";
}
private:
string& _out;
};
class AppendLibFeaClientIfNames {
public:
AppendLibFeaClientIfNames(string& out) : _out(out)
{}
void
operator() (const IfMgrIfTree::IfMap::value_type& v)
{
_out += v.first + " ";
}
private:
string& _out;
};
class AppendLibFeaClientVifNames {
public:
AppendLibFeaClientVifNames(string& out) : _out(out)
{}
void
operator() (const IfMgrIfAtom::VifMap::value_type& v)
{
_out += v.first + " ";
}
private:
string& _out;
};
class AppendLibFeaClientV4Addrs {
public:
AppendLibFeaClientV4Addrs(string& out) : _out(out)
{}
void
operator() (const IfMgrVifAtom::V4Map::value_type& v)
{
_out += v.first.str() + " ";
}
private:
string& _out;
};
class AppendLibFeaClientV6Addrs {
public:
AppendLibFeaClientV6Addrs(string& out) : _out(out)
{}
void
operator() (const IfMgrVifAtom::V6Map::value_type& v)
{
_out += v.first.str() + " ";
}
private:
string& _out;
};
/**
* Check IPv4 addresses.
*/
class CheckV4Addrs {
public:
CheckV4Addrs(const IfMgrVifAtom::V4Map& lfc_addrs,
string& errlog)
: _lfc_addrs(lfc_addrs), _errlog(errlog)
{}
void
operator() (const IfTreeVif::V4Map::value_type& v)
{
const IfTreeAddr4& ita = v.second;
IfMgrVifAtom::V4Map::const_iterator i = _lfc_addrs.find(ita.addr());
if (i == _lfc_addrs.end()) {
return;
}
const IfMgrIPv4Atom& ima = i->second;
if (ita.addr() != ima.addr()) {
_errlog += c_format("+ Addr4 %s mismatch %s != %s\n",
ita.addr().str().c_str(),
ita.addr().str().c_str(),
ima.addr().str().c_str());
}
if (ita.prefix_len() != ima.prefix_len()) {
_errlog += c_format("+ Addr4 %s prefix len mismatch %u != %u\n",
ita.addr().str().c_str(),
XORP_UINT_CAST(ita.prefix_len()),
XORP_UINT_CAST(ima.prefix_len()));
}
if (ita.enabled() != ima.enabled()) {
_errlog += c_format("+ Addr4 %s enabled mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.enabled()),
truth_of(ima.enabled()));
}
if (ita.broadcast() != ima.has_broadcast()) {
_errlog += c_format("+ Addr4 %s broadcast mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.broadcast()),
truth_of(ima.has_broadcast()));
}
if (ita.broadcast() && ita.bcast() != ima.broadcast_addr()) {
_errlog += c_format("+ Addr4 %s bcast addr mismatch %s != %s\n",
ita.addr().str().c_str(),
ita.bcast().str().c_str(),
ima.broadcast_addr().str().c_str());
}
if (ita.point_to_point() != ima.has_endpoint()) {
_errlog += c_format("+ Addr4 %s p2p mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.point_to_point()),
truth_of(ima.has_endpoint()));
}
if (ita.point_to_point() &&
ita.endpoint() != ima.endpoint_addr()) {
_errlog += c_format("+ Addr4 %s endpoint mismatch %s != %s\n",
ita.addr().str().c_str(),
ita.endpoint().str().c_str(),
ima.endpoint_addr().str().c_str());
}
if (ita.loopback() != ima.loopback()) {
_errlog += c_format("+ Addr4 %s loopback mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.loopback()),
truth_of(ima.loopback()));
}
if (ita.multicast() != ima.multicast_capable()) {
_errlog += c_format("+ Addr4 %s multicast mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.multicast()),
truth_of(ima.multicast_capable()));
}
}
private:
const IfMgrVifAtom::V4Map& _lfc_addrs;
string& _errlog;
};
/**
* Check IPv6 addresses.
*/
class CheckV6Addrs {
public:
CheckV6Addrs(const IfMgrVifAtom::V6Map& lfc_addrs,
string& errlog)
: _lfc_addrs(lfc_addrs), _errlog(errlog)
{}
void
operator() (const IfTreeVif::V6Map::value_type& v)
{
const IfTreeAddr6& ita = v.second;
IfMgrVifAtom::V6Map::const_iterator i = _lfc_addrs.find(ita.addr());
if (i == _lfc_addrs.end()) {
return;
}
const IfMgrIPv6Atom& ima = i->second;
if (ita.addr() != ima.addr()) {
_errlog += c_format("+ Addr6 %s mismatch %s != %s\n",
ita.addr().str().c_str(),
ita.addr().str().c_str(),
ima.addr().str().c_str());
}
if (ita.prefix_len() != ima.prefix_len()) {
_errlog += c_format("+ Addr6 %s prefix len mismatch %u != %u\n",
ita.addr().str().c_str(),
XORP_UINT_CAST(ita.prefix_len()),
XORP_UINT_CAST(ima.prefix_len()));
}
if (ita.enabled() != ima.enabled()) {
_errlog += c_format("+ Addr6 %s enabled mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.enabled()),
truth_of(ima.enabled()));
}
if (ita.point_to_point() != ima.has_endpoint()) {
_errlog += c_format("+ Addr6 %s p2p mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.point_to_point()),
truth_of(ima.has_endpoint()));
}
if (ita.point_to_point() &&
ita.endpoint() != ima.endpoint_addr()) {
_errlog += c_format("+ Addr6 %s endpoint mismatch %s != %s\n",
ita.addr().str().c_str(),
ita.endpoint().str().c_str(),
ima.endpoint_addr().str().c_str());
}
if (ita.loopback() != ima.loopback()) {
_errlog += c_format("+ Addr6 %s loopback mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.loopback()),
truth_of(ima.loopback()));
}
if (ita.multicast() != ima.multicast_capable()) {
_errlog += c_format("+ Addr6 %s multicast mismatch %s != %s\n",
ita.addr().str().c_str(),
truth_of(ita.multicast()),
truth_of(ima.multicast_capable()));
}
}
private:
const IfMgrVifAtom::V6Map& _lfc_addrs;
string& _errlog;
};
/**
* Check Virtual Interfaces class.
*/
class CheckVifs {
public:
CheckVifs(const IfMgrIfAtom::VifMap& lfc_vifs,
string& errlog)
: _lfc_vifs(lfc_vifs), _errlog(errlog)
{}
void
operator() (const IfTreeInterface::VifMap::value_type& v)
{
const IfTreeVif& itv = v.second;
IfMgrIfAtom::VifMap::const_iterator i = _lfc_vifs.find(itv.vifname());
if (i == _lfc_vifs.end()) {
return;
}
const IfMgrVifAtom& imv = i->second;
if (itv.vifname() != imv.name()) {
_errlog += c_format("+ Vif %s name mismatch %s != %s\n",
itv.vifname().c_str(),
itv.vifname().c_str(),
imv.name().c_str());
}
if (itv.enabled() != imv.enabled()) {
_errlog += c_format("+ Vif %s enabled mismatch %s != %s\n",
itv.vifname().c_str(),
truth_of(itv.enabled()),
truth_of(imv.enabled()));
}
if (itv.pif_index() != imv.pif_index()) {
_errlog += c_format("+ Vif %s pif_index mismatch %u != %u\n",
itv.vifname().c_str(),
itv.pif_index(),
imv.pif_index());
}
if (itv.multicast() != imv.multicast_capable()) {
_errlog += c_format("+ Vif %s multicast mismatch %s != %s\n",
itv.vifname().c_str(),
truth_of(itv.multicast()),
truth_of(imv.multicast_capable()));
}
if (itv.broadcast() != imv.broadcast_capable()) {
_errlog += c_format("+ Vif %s broadcast mismatch %s != %s\n",
itv.vifname().c_str(),
truth_of(itv.broadcast()),
truth_of(imv.broadcast_capable()));
}
if (itv.point_to_point() != imv.p2p_capable()) {
_errlog += c_format("+ Vif %s point_to_point mismatch %s != %s\n",
itv.vifname().c_str(),
truth_of(itv.point_to_point()),
truth_of(imv.p2p_capable()));
}
if (itv.loopback() != imv.loopback()) {
_errlog += c_format("+ Vif %s loopback mismatch %s != %s\n",
itv.vifname().c_str(),
truth_of(itv.loopback()),
truth_of(imv.loopback()));
}
if (itv.v4addrs().size() != imv.ipv4addrs().size()) {
_errlog += "Vif %s IPv4 address count mismatch\n";
string fv4a;
for_each(itv.v4addrs().begin(), itv.v4addrs().end(),
AppendFeaV4Addrs(fv4a));
_errlog += " Fea Iftree v4addrs = " + fv4a + "\n";
string lfv4a;
for_each(imv.ipv4addrs().begin(), imv.ipv4addrs().end(),
AppendLibFeaClientV4Addrs(lfv4a));
_errlog += " LibFeaClient Iftree v4addrs = " + lfv4a + "\n";
}
if (itv.v6addrs().size() != imv.ipv6addrs().size()) {
_errlog += "Vif %s IPv6 address count mismatch\n";
string fv6a;
for_each(itv.v6addrs().begin(), itv.v6addrs().end(),
AppendFeaV6Addrs(fv6a));
_errlog += " Fea Iftree v6addrs = " + fv6a + "\n";
string lfv6a;
for_each(imv.ipv6addrs().begin(), imv.ipv6addrs().end(),
AppendLibFeaClientV6Addrs(lfv6a));
_errlog += " LibFeaClient Iftree v6addrs = " + lfv6a + "\n";
}
for_each(itv.v4addrs().begin(), itv.v4addrs().end(),
CheckV4Addrs(imv.ipv4addrs(), _errlog));
}
private:
const IfMgrIfAtom::VifMap& _lfc_vifs;
string& _errlog;
};
/**
* Check Interfaces class.
*/
class CheckIfs {
public:
CheckIfs(const IfMgrIfTree::IfMap& lfc_ifs,
string& errlog)
: _lfc_ifs(lfc_ifs), _errlog(errlog)
{}
void
operator() (const IfTree::IfMap::value_type& v)
{
const IfTreeInterface& ifi = v.second;
IfMgrIfTree::IfMap::const_iterator i = _lfc_ifs.find(ifi.name());
if (i == _lfc_ifs.end()) {
return;
}
const IfMgrIfAtom& imi = i->second;
if (ifi.enabled() != imi.enabled()) {
_errlog += c_format("+ Interface %s enabled %d != %d\n",
ifi.name().c_str(),
ifi.enabled(), imi.enabled());
}
if (ifi.mtu() != imi.mtu_bytes()) {
_errlog += c_format("+ Interface %s mtu %u != %u\n",
ifi.name().c_str(),
XORP_UINT_CAST(ifi.mtu()),
XORP_UINT_CAST(imi.mtu_bytes()));
}
if (ifi.mac() != imi.mac()) {
_errlog += c_format("+ Interface %s mac %s != %s\n",
ifi.name().c_str(),
ifi.mac().str().c_str(),
imi.mac().str().c_str());
}
if (ifi.pif_index() != imi.pif_index()) {
_errlog += c_format("+ Interface %s pif_index %u != %u\n",
ifi.name().c_str(),
ifi.pif_index(),
imi.pif_index());
}
if (ifi.no_carrier() != imi.no_carrier()) {
_errlog += c_format("+ Interface %s no_carrier %s != %s\n",
ifi.name().c_str(),
ifi.no_carrier()? "true" : "false",
imi.no_carrier()? "true" : "false");
}
if (ifi.vifs().size() != imi.vifs().size()) {
_errlog += "Interface %s vif count mismatch\n";
string fvifs;
for_each(ifi.vifs().begin(), ifi.vifs().end(),
AppendFeaVifNames(fvifs));
_errlog += " Fea IfTree vifs = " + fvifs + "\n";
string lvifs;
for_each(imi.vifs().begin(), imi.vifs().end(),
AppendLibFeaClientVifNames(lvifs));
_errlog += " LibFeaClient IfTree vifs = " + lvifs + "\n";
}
for_each(ifi.vifs().begin(), ifi.vifs().end(),
CheckVifs(imi.vifs(), _errlog));
}
private:
const IfMgrIfTree::IfMap& _lfc_ifs;
string& _errlog;
};
bool
equivalent(const IfTree& fea_iftree,
const IfMgrIfTree& lfc_iftree,
string& errlog)
{
errlog.erase();
if (fea_iftree.ifs().size() != lfc_iftree.ifs().size()) {
string fifs, lifs;
for_each(fea_iftree.ifs().begin(), fea_iftree.ifs().end(),
AppendFeaIfNames(fifs));
for_each(lfc_iftree.ifs().begin(), lfc_iftree.ifs().end(),
AppendLibFeaClientIfNames(fifs));
errlog += "Interface count mismatch\n";
errlog += " Fea IfTree interfaces = " + fifs + "\n";
errlog += " LibFeaClient IfTree interfaces = " + lifs + "\n";
}
for_each(fea_iftree.ifs().begin(), fea_iftree.ifs().end(),
CheckIfs(lfc_iftree.ifs(), errlog));
return errlog.empty();
}
syntax highlighted by Code2HTML, v. 0.9.1