Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 257 additions & 0 deletions src/DbInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

#include <algorithm>
#include <tuple>
#include <vector>
#include <functional>

#include <boost/algorithm/string.hpp>
#include <boost/bind/bind.hpp>
Expand Down Expand Up @@ -323,6 +325,9 @@ void DbInterface::initialize()
mAppDbForwardingCommandTablePtr = std::make_shared<swss::Table> (
mAppDbPtr.get(), APP_FORWARDING_STATE_COMMAND_TABLE_NAME
);
mAppDbIcmpEchoSessionTablePtr = std::make_shared<swss::ProducerStateTable> (
mAppDbPtr.get(), APP_ICMP_ECHO_SESSION_TABLE_NAME
);
mStateDbMuxLinkmgrTablePtr = std::make_shared<swss::Table> (
mStateDbPtr.get(), STATE_MUX_LINKMGR_TABLE_NAME
);
Expand All @@ -335,7 +340,11 @@ void DbInterface::initialize()
mStateDbSwitchCauseTablePtr = std::make_shared<swss::Table> (
mStateDbPtr.get(), STATE_MUX_SWITCH_CAUSE_TABLE_NAME
);
mStateDbIcmpEchoSessionTablePtr = std::make_shared<swss::Table> (
mStateDbPtr.get(), STATE_ICMP_ECHO_SESSION_TABLE_NAME
);
mMuxStateTablePtr = std::make_shared<swss::Table> (mStateDbPtr.get(), STATE_MUX_CABLE_TABLE_NAME);
mSwitchCapTablePtr = std::make_shared<swss::Table> (mStateDbPtr.get(), STATE_SWITCH_CAPABILITY_TABLE_NAME);

mSwssThreadPtr = std::make_shared<boost::thread> (&DbInterface::handleSwssNotification, this);
}
Expand Down Expand Up @@ -808,6 +817,61 @@ void DbInterface::getPortCableType(std::shared_ptr<swss::DBConnector> configDbCo
processPortCableType(entries);
}

//
// ---> processProberType(std::vector<swss::KeyOpFieldsValuesTuple> &entries);
//
// process Mux Cable Table enteries to get proberType by defaut its software
//
void DbInterface::processProberType(std::vector<swss::KeyOpFieldsValuesTuple> &entries)
{
// check hardware capability
static bool hw_offload_capable = false;
std::string capable;
if (mSwitchCapTablePtr && mSwitchCapTablePtr->hget("switch", "ICMP_OFFLOAD_CAPABLE", capable))
{
if (capable == "true")
{
hw_offload_capable = true;
MUXLOGWARNING(boost::format("Hardware Link Prober capability detected"));
}
}

for (auto &entry: entries) {
std::string portName = kfvKey(entry);
std::string operation = kfvOp(entry);
std::vector<swss::FieldValueTuple> fieldValues = kfvFieldsValues(entry);

std::string field = "prober_type";
std::vector<swss::FieldValueTuple>::const_iterator cit = std::find_if(
fieldValues.cbegin(),
fieldValues.cend(),
[&field] (const swss::FieldValueTuple &fv) {return fvField(fv) == field;}
);
std::string proberType = ((hw_offload_capable && cit != fieldValues.cend()) ?
cit->second : "software");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add checker for value? in case of invalid input?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm, saw you deferred it to mux port

MUXLOGWARNING(boost::format("%s: Link Prober type = {%s}") % portName % proberType);

MUXLOGDEBUG(boost::format("port: %s, %s = %s") % portName % field % proberType);

mMuxManagerPtr->updateProberType(portName, proberType);
}
}

//
// ---> getPortCableType(std::shared_ptr<swss::DBConnector> configDbConnector);
//
// retrieve the Link Failure Detection Type (HW/SW) from config
//
void DbInterface::getProberType(std::shared_ptr<swss::DBConnector> configDbConnector)
{
MUXLOGINFO("Reading prober_type");
swss::Table configDbMuxCableTable(configDbConnector.get(), CFG_MUX_CABLE_TABLE_NAME);
std::vector<swss::KeyOpFieldsValuesTuple> entries;

configDbMuxCableTable.getContent(entries);
processProberType(entries);
}

//
// ---> processSoCIpAddress(std::vector<swss::KeyOpFieldsValuesTuple> &entries);
//
Expand Down Expand Up @@ -1524,6 +1588,193 @@ void DbInterface::processTsaEnableNotification(std::deque<swss::KeyOpFieldsValue
}
}

//
// ---> createIcmpEchoSession(std::string key, IcmpHwOffloadEntriesPtr entries);
//
// triggers creation of a ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABLE
//
void DbInterface::createIcmpEchoSession(std::string key, IcmpHwOffloadEntriesPtr entries)
{
MUXLOGDEBUG(boost::format(" %s : ICMP session Being created ") % key);
boost::asio::post(mStrand, boost::bind(
&DbInterface::handleIcmpEchoSession,
this,
key,
entries.release()
));
}

//
// ---> handleIcmpEchoSession(std::string key, IcmpHwOffloadEntries *entries);
//
// handles creation of a ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABLE
//
void DbInterface::handleIcmpEchoSession(std::string key, IcmpHwOffloadEntries *entries)
{
std::vector<swss::FieldValueTuple> fvs;
for(auto& entry : *entries) {
const std::string field = entry.first;
const std::string value = entry.second;
fvs.emplace_back(field, value);
MUXLOGDEBUG(boost::format("APP_ICMP_ECHO_SESSION_TABLE::key: %s, field: %s, value: %s") %
key %
field %
value
);
}
mAppDbIcmpEchoSessionTablePtr->set(key, fvs);
delete entries;
}

//
// ---> updateIntervalv4(uint32_t tx_interval, uint32_t rx_interval);
//
// handles interval_v4 field for ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABLE
//
void DbInterface::updateIntervalv4(uint32_t tx_interval, uint32_t rx_interval)
{
MUXLOGDEBUG(boost::format("Updating Interval v4 tx(%u) rx(%u)") %
tx_interval % rx_interval);
boost::asio::post(mStrand, boost::bind(
&DbInterface::handleUpdateInterval,
this,
tx_interval,
rx_interval
));
}

//
// ---> updateIntervalv6(uint32_t tx_interval, uint32_t rx_interval);
//
// handles update of interval_v6 field for ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABLE
//
void DbInterface::updateIntervalv6(uint32_t tx_interval, uint32_t rx_interval)
{
MUXLOGDEBUG(boost::format("Updating Interval v6 tx(%u) rx(%u)") %
tx_interval % rx_interval);
boost::asio::post(mStrand, boost::bind(
&DbInterface::handleUpdateInterval,
this,
tx_interval,
rx_interval
));
}

//
// --->handleUpdateInterval(uint32_t tx_interval, uint32_t rx_interval);
//
// handles update of tx/rx interval field for ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABL
//
void DbInterface::handleUpdateInterval(uint32_t tx_interval, uint32_t rx_interval)
{
std::shared_ptr<swss::DBConnector> appDbPtr = std::make_shared<swss::DBConnector> ("APPL_DB", 0);
swss::Table icmpAppDbTbl(appDbPtr.get(), APP_ICMP_ECHO_SESSION_TABLE_NAME);
std::vector<std::string> keys;
icmpAppDbTbl.getKeys(keys);
std::vector<swss::FieldValueTuple> fvs;
fvs.emplace_back("tx_interval", std::to_string(tx_interval));
fvs.emplace_back("rx_interval", std::to_string(rx_interval));
for (auto& key : keys)
{
mAppDbIcmpEchoSessionTablePtr->set(key, fvs);
}
}

//
// ---> deleteIcmpEchoSession(std::string key);
//
// handles deletion of a ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABLE
//
void DbInterface::deleteIcmpEchoSession(std::string key)
{
MUXLOGDEBUG(boost::format("%s : ICMP session Being deleted") % key);
boost::asio::post(mStrand, boost::bind(
&DbInterface::handleDeleteIcmpEchoSession,
this,
key
));
}

//
// ---> handleDeleteIcmpEchoSession(std::string key);
//
// handles deletion of a ICMP_ECHO_SESSION in APP_ICMP_ECHO_SESSION_TABLE
//
void DbInterface::handleDeleteIcmpEchoSession(std::string key) {
MUXLOGDEBUG(boost::format("APP_ICMP_ECHO_SESSION_TABLE::key: %s ") %
key
);
mAppDbIcmpEchoSessionTablePtr->del(key);
}

//
// ---> extractIfnameAndSessionType(const std::string &key, std::string &ifname, std::string &sessionType);
//
// helper function to extract interface name and session_type from the key
//
void DbInterface::extractIfnameAndSessionType(const std::string &key, std::string &ifname, std::string &sessionType)
{
size_t firstSep = key.find('|');
size_t secondSep = key.find('|', firstSep + 1);
size_t thirdSep = key.find('|', secondSep + 1);

if (firstSep != std::string::npos &&
secondSep != std::string::npos &&
thirdSep != std::string::npos) {
ifname = key.substr(firstSep + 1, secondSep - firstSep - 1);
sessionType = key.substr(thirdSep + 1);
} else {
std::cerr << "Unexpected format: " << key << std::endl;
}
}

//
// ---> processIcmpEchoSessionStateNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries);
//
// process each entery of ICMP_ECHO_SESSION_TABLE extract Port, Session_Type(Normal/Rx) and state itself
//
void DbInterface::processIcmpEchoSessionStateNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries)
{
for (auto &entry: entries) {
std::string key = kfvKey(entry);
std::string port;
std::string session_type;
extractIfnameAndSessionType(key, port, session_type);
std::string opertation = kfvOp(entry);
std::vector<swss::FieldValueTuple> fieldValues = kfvFieldsValues(entry);

std::vector<swss::FieldValueTuple>::const_iterator cit = std::find_if(
fieldValues.cbegin(),
fieldValues.cend(),
[] (const swss::FieldValueTuple &fv) {return fvField(fv) == "state";}
);
if (cit != fieldValues.cend()) {
const std::string field = cit->first;
const std::string value = cit->second;

MUXLOGINFO(boost::format("port: %s, f: %s, v: %s") %
port %
field %
value
);
mMuxManagerPtr->updateLinkFailureDetectionState(port, value, session_type);
}
}
}

//
// ---> handleIcmpEchoSessionStateNotification(swss::SubscriberStateTable &stateDbIcmpEchoSessionTable);
//
// extract enteries from State_DB ICMP_ECHO_SESSION_TABLE and call processing function
//
void DbInterface::handleIcmpEchoSessionStateNotification(swss::SubscriberStateTable &stateDbIcmpEchoSessionTable)
{
std::deque<swss::KeyOpFieldsValuesTuple> entries;

stateDbIcmpEchoSessionTable.pops(entries);
processIcmpEchoSessionStateNotification(entries);
}

//
// ---> handleSwssNotification();
//
Expand Down Expand Up @@ -1556,11 +1807,14 @@ void DbInterface::handleSwssNotification()
swss::SubscriberStateTable stateDbMuxInfoTable(stateDbPtr.get(), MUX_CABLE_INFO_TABLE);
// for getting peer's admin forwarding state
swss::SubscriberStateTable stateDbPeerMuxTable(stateDbPtr.get(), STATE_PEER_HW_FORWARDING_STATE_TABLE_NAME);
// for getting icmp echo session state
swss::SubscriberStateTable stateDbIcmpEchoSessionTable(stateDbPtr.get(), STATE_ICMP_ECHO_SESSION_TABLE_NAME);

getTorMacAddress(configDbPtr);
getVlanNames(configDbPtr);
getLoopback2InterfaceInfo(configDbPtr);
getPortCableType(configDbPtr);
getProberType(configDbPtr);
getServerIpAddress(configDbPtr);
getSoCIpAddress(configDbPtr);

Expand All @@ -1584,6 +1838,7 @@ void DbInterface::handleSwssNotification()
swssSelect.addSelectable(&stateDbMuxInfoTable);
swssSelect.addSelectable(&stateDbPeerMuxTable);
swssSelect.addSelectable(&netlinkNeighbor);
swssSelect.addSelectable(&stateDbIcmpEchoSessionTable);

while (mPollSwssNotifcation) {
swss::Selectable *selectable;
Expand Down Expand Up @@ -1619,6 +1874,8 @@ void DbInterface::handleSwssNotification()
handlePeerLinkStateNotification(stateDbMuxInfoTable);
} else if (selectable == static_cast<swss::Selectable *> (&stateDbPeerMuxTable)) {
handlePeerMuxStateNotification(stateDbPeerMuxTable);
} else if (selectable == static_cast<swss::Selectable *> (&stateDbIcmpEchoSessionTable)) {
handleIcmpEchoSessionStateNotification(stateDbIcmpEchoSessionTable);
} else if (selectable == static_cast<swss::Selectable *> (&netlinkNeighbor)) {
continue;
} else {
Expand Down
Loading
Loading