forked from sonic-net/sonic-buildimage
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement telemetry daemon for teamd (sonic-net#1317)
* Implement telemetry daemon for teamd Every second all presented teamd daemons is going to be requested for the state dump in json format. After that the json dump will be converted to the memory structure represented the desired format. The database is going to be updated only for entries which were changed since the last poll. The daemon will track a case when a LAG has been added or removed. * Fix typos * Fix order in the class declaration * Make the code more c++ * Add more changes to .gitignore Co-authored-by: PS <ps@cs.com>
- Loading branch information
1 parent
7cc71d1
commit cbfe521
Showing
9 changed files
with
781 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
INCLUDES = -I $(top_srcdir) | ||
|
||
bin_PROGRAMS = tlm_teamd | ||
|
||
if DEBUG | ||
DBGFLAGS = -ggdb -DDEBUG | ||
else | ||
DBGFLAGS = -g | ||
endif | ||
|
||
tlm_teamd_SOURCES = main.cpp teamdctl_mgr.cpp values_store.cpp | ||
|
||
tlm_teamd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) | ||
tlm_teamd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(JANSSON_CFLAGS) | ||
tlm_teamd_LDADD = -lhiredis -lswsscommon -lteamdctl $(JANSSON_LIBS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#include <csignal> | ||
#include <iostream> | ||
#include <deque> | ||
|
||
#include <logger.h> | ||
#include <select.h> | ||
#include <dbconnector.h> | ||
#include <subscriberstatetable.h> | ||
|
||
#include "teamdctl_mgr.h" | ||
#include "values_store.h" | ||
|
||
|
||
bool g_run = true; | ||
|
||
|
||
/// This function extract all available updates from the table | ||
/// and add or remove LAG interfaces from the TeamdCtlMgr | ||
/// | ||
/// @param table reference to the SubscriberStateTable | ||
/// @param mgr reference to the TeamdCtlMgr | ||
/// | ||
void update_interfaces(swss::SubscriberStateTable & table, TeamdCtlMgr & mgr) | ||
{ | ||
std::deque<swss::KeyOpFieldsValuesTuple> entries; | ||
|
||
table.pops(entries); | ||
for (const auto & entry: entries) | ||
{ | ||
const auto & lag_name = kfvKey(entry); | ||
const auto & op = kfvOp(entry); | ||
|
||
if (op == "SET") | ||
{ | ||
mgr.add_lag(lag_name); | ||
} | ||
else if (op == "DEL") | ||
{ | ||
mgr.remove_lag(lag_name); | ||
} | ||
else | ||
{ | ||
SWSS_LOG_WARN("Got invalid operation: '%s' with key '%s'", op.c_str(), lag_name.c_str()); | ||
} | ||
} | ||
} | ||
|
||
/// | ||
/// Signal handler | ||
/// | ||
void sig_handler(int signo) | ||
{ | ||
(void)signo; | ||
g_run = false; | ||
} | ||
|
||
/// | ||
/// main function | ||
/// | ||
int main() | ||
{ | ||
const int ms_select_timeout = 1000; | ||
|
||
sighandler_t sig_res; | ||
|
||
sig_res = signal(SIGTERM, sig_handler); | ||
if (sig_res == SIG_ERR) | ||
{ | ||
std::cerr << "Can't set signal handler for SIGTERM\n"; | ||
return -1; | ||
} | ||
|
||
sig_res = signal(SIGINT, sig_handler); | ||
if (sig_res == SIG_ERR) | ||
{ | ||
std::cerr << "Can't set signal handler for SIGINT\n"; | ||
return -1; | ||
} | ||
|
||
int rc = 0; | ||
try | ||
{ | ||
swss::Logger::linkToDbNative("tlm_teamd"); | ||
SWSS_LOG_NOTICE("Starting"); | ||
swss::DBConnector db("STATE_DB", 0); | ||
|
||
ValuesStore values_store(&db); | ||
TeamdCtlMgr teamdctl_mgr; | ||
|
||
swss::Select s; | ||
swss::Selectable * event; | ||
swss::SubscriberStateTable sst_lag(&db, STATE_LAG_TABLE_NAME); | ||
s.addSelectable(&sst_lag); | ||
|
||
while (g_run && rc == 0) | ||
{ | ||
int res = s.select(&event, ms_select_timeout); | ||
if (res == swss::Select::OBJECT) | ||
{ | ||
update_interfaces(sst_lag, teamdctl_mgr); | ||
values_store.update(teamdctl_mgr.get_dumps()); | ||
} | ||
else if (res == swss::Select::ERROR) | ||
{ | ||
SWSS_LOG_ERROR("Select returned ERROR"); | ||
rc = -2; | ||
} | ||
else if (res == swss::Select::TIMEOUT) | ||
{ | ||
values_store.update(teamdctl_mgr.get_dumps()); | ||
} | ||
else | ||
{ | ||
SWSS_LOG_ERROR("Select returned unknown value"); | ||
rc = -3; | ||
} | ||
} | ||
SWSS_LOG_NOTICE("Exiting"); | ||
} | ||
catch (const std::exception & e) | ||
{ | ||
std::cerr << "Exception \"" << e.what() << "\" had been thrown" << std::endl; | ||
SWSS_LOG_ERROR("Exception '%s' had been thrown", e.what()); | ||
rc = -1; | ||
} | ||
|
||
return rc; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#include <cstring> | ||
|
||
#include <logger.h> | ||
|
||
#include "teamdctl_mgr.h" | ||
|
||
/// | ||
/// The destructor clean up handlers to teamds | ||
/// | ||
TeamdCtlMgr::~TeamdCtlMgr() | ||
{ | ||
for (const auto & p: m_handlers) | ||
{ | ||
const auto & lag_name = p.first; | ||
const auto & tdc = m_handlers[lag_name]; | ||
teamdctl_disconnect(tdc); | ||
teamdctl_free(tdc); | ||
SWSS_LOG_NOTICE("Exiting. Disconnecting from teamd. LAG '%s'", lag_name.c_str()); | ||
} | ||
} | ||
|
||
/// | ||
/// Returns true, if we have LAG with name lag_name | ||
/// in the manager. | ||
/// @param lag_name a name for LAG interface | ||
/// @return true if has key, false if doesn't | ||
/// | ||
bool TeamdCtlMgr::has_key(const std::string & lag_name) const | ||
{ | ||
return m_handlers.find(lag_name) != m_handlers.end(); | ||
} | ||
|
||
/// | ||
/// Adds a LAG interface with lag_name to the manager | ||
/// This method allocates structures to connect to teamd | ||
/// @param lag_name a name for LAG interface | ||
/// @return true if the lag was added successfully, false otherwise | ||
/// | ||
bool TeamdCtlMgr::add_lag(const std::string & lag_name) | ||
{ | ||
if (has_key(lag_name)) | ||
{ | ||
SWSS_LOG_DEBUG("The LAG '%s' was already added. Skip adding it.", lag_name.c_str()); | ||
return true; | ||
} | ||
else | ||
{ | ||
auto tdc = teamdctl_alloc(); | ||
if (!tdc) | ||
{ | ||
SWSS_LOG_ERROR("Can't allocate memory for teamdctl handler. LAG='%s'", lag_name.c_str()); | ||
return false; | ||
} | ||
|
||
int err = teamdctl_connect(tdc, lag_name.c_str(), nullptr, nullptr); | ||
if (err) | ||
{ | ||
SWSS_LOG_ERROR("Can't connect to teamd LAG='%s', error='%s'", lag_name.c_str(), strerror(-err)); | ||
teamdctl_free(tdc); | ||
return false; | ||
} | ||
m_handlers.emplace(lag_name, tdc); | ||
SWSS_LOG_NOTICE("The LAG '%s' has been added.", lag_name.c_str()); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/// | ||
/// Removes a LAG interface with lag_name from the manager | ||
/// This method deallocates teamd structures | ||
/// @param lag_name a name for LAG interface | ||
/// @return true if the lag was removed successfully, false otherwise | ||
/// | ||
bool TeamdCtlMgr::remove_lag(const std::string & lag_name) | ||
{ | ||
if (has_key(lag_name)) | ||
{ | ||
auto tdc = m_handlers[lag_name]; | ||
teamdctl_disconnect(tdc); | ||
teamdctl_free(tdc); | ||
m_handlers.erase(lag_name); | ||
SWSS_LOG_NOTICE("The LAG '%s' has been removed.", lag_name.c_str()); | ||
} | ||
else | ||
{ | ||
SWSS_LOG_WARN("The LAG '%s' hasn't been added. Can't remove it", lag_name.c_str()); | ||
} | ||
return true; | ||
} | ||
|
||
/// | ||
/// Get json dump from teamd for LAG interface with name lag_name | ||
/// @param lag_name a name for LAG interface | ||
/// @return a pair. First element of the pair is true, if the method is successful | ||
/// false otherwise. If the first element is true, the second element has a dump | ||
/// otherwise the second element is an empty string | ||
/// | ||
TeamdCtlDump TeamdCtlMgr::get_dump(const std::string & lag_name) | ||
{ | ||
TeamdCtlDump res = { false, "" }; | ||
if (has_key(lag_name)) | ||
{ | ||
auto tdc = m_handlers[lag_name]; | ||
char * dump; | ||
int r = teamdctl_state_get_raw_direct(tdc, &dump); | ||
if (r == 0) | ||
{ | ||
res = { true, std::string(dump) }; | ||
} | ||
else | ||
{ | ||
SWSS_LOG_ERROR("Can't get dump for LAG '%s'. Skipping", lag_name.c_str()); | ||
} | ||
} | ||
else | ||
{ | ||
SWSS_LOG_ERROR("Can't update state. LAG not found. LAG='%s'", lag_name.c_str()); | ||
} | ||
|
||
return res; | ||
} | ||
|
||
/// | ||
/// Get dumps for all registered LAG interfaces | ||
/// @return vector of pairs. Each pair first value is a name of LAG, second value is a dump | ||
/// | ||
TeamdCtlDumps TeamdCtlMgr::get_dumps() | ||
{ | ||
TeamdCtlDumps res; | ||
|
||
for (const auto & p: m_handlers) | ||
{ | ||
const auto & lag_name = p.first; | ||
const auto & result = get_dump(lag_name); | ||
const auto & status = result.first; | ||
const auto & dump = result.second; | ||
if (status) | ||
{ | ||
res.push_back({ lag_name, dump }); | ||
} | ||
} | ||
|
||
return res; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
#include <unordered_map> | ||
|
||
#include <teamdctl.h> | ||
|
||
using TeamdCtlDump = std::pair<bool, std::string>; | ||
using TeamdCtlDumpsEntry = std::pair<std::string, std::string>; | ||
using TeamdCtlDumps = std::vector<TeamdCtlDumpsEntry>; | ||
|
||
class TeamdCtlMgr | ||
{ | ||
public: | ||
TeamdCtlMgr() = default; | ||
~TeamdCtlMgr(); | ||
bool add_lag(const std::string & kag_name); | ||
bool remove_lag(const std::string & kag_name); | ||
TeamdCtlDump get_dump(const std::string & lag_name); | ||
TeamdCtlDumps get_dumps(); | ||
|
||
private: | ||
bool has_key(const std::string & lag_name) const; | ||
|
||
std::unordered_map<std::string, struct teamdctl*> m_handlers; | ||
}; |
Oops, something went wrong.