Skip to content

Commit cbfe521

Browse files
pavel-shirshovPS
and
PS
authored
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>
1 parent 7cc71d1 commit cbfe521

9 files changed

+781
-1
lines changed

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ libtool
3030
Makefile.in
3131
stamp-h1
3232
**/Makefile
33+
autom4te.cache
3334

3435
# Dependency Folder #
3536
#####################
3637
deps/
38+
**/.deps
3739

3840
# Executables #
3941
###############
@@ -47,6 +49,9 @@ cfgmgr/teammgrd
4749
cfgmgr/vlanmgrd
4850
cfgmgr/vrfmgrd
4951
cfgmgr/vxlanmgrd
52+
cfgmgr/natmgrd
53+
cfgmgr/sflowmgrd
54+
portsyncd/portsyncd
5055
fpmsyncd/fpmsyncd
5156
mclagsyncd/mclagsyncd
5257
natsyncd/natsyncd
@@ -57,11 +62,16 @@ orchagent/routeresync
5762
portsyncd/portsyncd
5863
swssconfig/swssconfig
5964
swssconfig/swssplayer
65+
tlm_teamd/tlm_teamd
6066
teamsyncd/teamsyncd
6167
tests/tests
6268

6369
# Test Files #
6470
##############
71+
tests/log
72+
tests/mock_tests/test-suite.log
73+
tests/mock_tests/tests.log
74+
tests/mock_tests/tests.trs
6575
tests/test-suite.log
6676
tests/tests.log
6777
tests/tests.trs

Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
SUBDIRS = fpmsyncd neighsyncd portsyncd mclagsyncd natsyncd orchagent swssconfig cfgmgr tests
33

44
if HAVE_LIBTEAM
5-
SUBDIRS += teamsyncd
5+
SUBDIRS += teamsyncd tlm_teamd
66
endif

configure.ac

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ AC_CHECK_LIB([team], [team_alloc],
2020
[AC_MSG_WARN([libteam is not installed.])
2121
AM_CONDITIONAL(HAVE_LIBTEAM, false)])
2222

23+
PKG_CHECK_MODULES([JANSSON], [jansson])
24+
2325
AC_CHECK_LIB([sai], [sai_object_type_query],
2426
AM_CONDITIONAL(HAVE_SAI, true),
2527
[AC_MSG_WARN([libsai is not installed.])
@@ -92,6 +94,7 @@ AC_CONFIG_FILES([
9294
natsyncd/Makefile
9395
portsyncd/Makefile
9496
teamsyncd/Makefile
97+
tlm_teamd/Makefile
9598
mclagsyncd/Makefile
9699
swssconfig/Makefile
97100
cfgmgr/Makefile

tlm_teamd/Makefile.am

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
INCLUDES = -I $(top_srcdir)
2+
3+
bin_PROGRAMS = tlm_teamd
4+
5+
if DEBUG
6+
DBGFLAGS = -ggdb -DDEBUG
7+
else
8+
DBGFLAGS = -g
9+
endif
10+
11+
tlm_teamd_SOURCES = main.cpp teamdctl_mgr.cpp values_store.cpp
12+
13+
tlm_teamd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
14+
tlm_teamd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(JANSSON_CFLAGS)
15+
tlm_teamd_LDADD = -lhiredis -lswsscommon -lteamdctl $(JANSSON_LIBS)

tlm_teamd/main.cpp

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#include <csignal>
2+
#include <iostream>
3+
#include <deque>
4+
5+
#include <logger.h>
6+
#include <select.h>
7+
#include <dbconnector.h>
8+
#include <subscriberstatetable.h>
9+
10+
#include "teamdctl_mgr.h"
11+
#include "values_store.h"
12+
13+
14+
bool g_run = true;
15+
16+
17+
/// This function extract all available updates from the table
18+
/// and add or remove LAG interfaces from the TeamdCtlMgr
19+
///
20+
/// @param table reference to the SubscriberStateTable
21+
/// @param mgr reference to the TeamdCtlMgr
22+
///
23+
void update_interfaces(swss::SubscriberStateTable & table, TeamdCtlMgr & mgr)
24+
{
25+
std::deque<swss::KeyOpFieldsValuesTuple> entries;
26+
27+
table.pops(entries);
28+
for (const auto & entry: entries)
29+
{
30+
const auto & lag_name = kfvKey(entry);
31+
const auto & op = kfvOp(entry);
32+
33+
if (op == "SET")
34+
{
35+
mgr.add_lag(lag_name);
36+
}
37+
else if (op == "DEL")
38+
{
39+
mgr.remove_lag(lag_name);
40+
}
41+
else
42+
{
43+
SWSS_LOG_WARN("Got invalid operation: '%s' with key '%s'", op.c_str(), lag_name.c_str());
44+
}
45+
}
46+
}
47+
48+
///
49+
/// Signal handler
50+
///
51+
void sig_handler(int signo)
52+
{
53+
(void)signo;
54+
g_run = false;
55+
}
56+
57+
///
58+
/// main function
59+
///
60+
int main()
61+
{
62+
const int ms_select_timeout = 1000;
63+
64+
sighandler_t sig_res;
65+
66+
sig_res = signal(SIGTERM, sig_handler);
67+
if (sig_res == SIG_ERR)
68+
{
69+
std::cerr << "Can't set signal handler for SIGTERM\n";
70+
return -1;
71+
}
72+
73+
sig_res = signal(SIGINT, sig_handler);
74+
if (sig_res == SIG_ERR)
75+
{
76+
std::cerr << "Can't set signal handler for SIGINT\n";
77+
return -1;
78+
}
79+
80+
int rc = 0;
81+
try
82+
{
83+
swss::Logger::linkToDbNative("tlm_teamd");
84+
SWSS_LOG_NOTICE("Starting");
85+
swss::DBConnector db("STATE_DB", 0);
86+
87+
ValuesStore values_store(&db);
88+
TeamdCtlMgr teamdctl_mgr;
89+
90+
swss::Select s;
91+
swss::Selectable * event;
92+
swss::SubscriberStateTable sst_lag(&db, STATE_LAG_TABLE_NAME);
93+
s.addSelectable(&sst_lag);
94+
95+
while (g_run && rc == 0)
96+
{
97+
int res = s.select(&event, ms_select_timeout);
98+
if (res == swss::Select::OBJECT)
99+
{
100+
update_interfaces(sst_lag, teamdctl_mgr);
101+
values_store.update(teamdctl_mgr.get_dumps());
102+
}
103+
else if (res == swss::Select::ERROR)
104+
{
105+
SWSS_LOG_ERROR("Select returned ERROR");
106+
rc = -2;
107+
}
108+
else if (res == swss::Select::TIMEOUT)
109+
{
110+
values_store.update(teamdctl_mgr.get_dumps());
111+
}
112+
else
113+
{
114+
SWSS_LOG_ERROR("Select returned unknown value");
115+
rc = -3;
116+
}
117+
}
118+
SWSS_LOG_NOTICE("Exiting");
119+
}
120+
catch (const std::exception & e)
121+
{
122+
std::cerr << "Exception \"" << e.what() << "\" had been thrown" << std::endl;
123+
SWSS_LOG_ERROR("Exception '%s' had been thrown", e.what());
124+
rc = -1;
125+
}
126+
127+
return rc;
128+
}

tlm_teamd/teamdctl_mgr.cpp

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#include <cstring>
2+
3+
#include <logger.h>
4+
5+
#include "teamdctl_mgr.h"
6+
7+
///
8+
/// The destructor clean up handlers to teamds
9+
///
10+
TeamdCtlMgr::~TeamdCtlMgr()
11+
{
12+
for (const auto & p: m_handlers)
13+
{
14+
const auto & lag_name = p.first;
15+
const auto & tdc = m_handlers[lag_name];
16+
teamdctl_disconnect(tdc);
17+
teamdctl_free(tdc);
18+
SWSS_LOG_NOTICE("Exiting. Disconnecting from teamd. LAG '%s'", lag_name.c_str());
19+
}
20+
}
21+
22+
///
23+
/// Returns true, if we have LAG with name lag_name
24+
/// in the manager.
25+
/// @param lag_name a name for LAG interface
26+
/// @return true if has key, false if doesn't
27+
///
28+
bool TeamdCtlMgr::has_key(const std::string & lag_name) const
29+
{
30+
return m_handlers.find(lag_name) != m_handlers.end();
31+
}
32+
33+
///
34+
/// Adds a LAG interface with lag_name to the manager
35+
/// This method allocates structures to connect to teamd
36+
/// @param lag_name a name for LAG interface
37+
/// @return true if the lag was added successfully, false otherwise
38+
///
39+
bool TeamdCtlMgr::add_lag(const std::string & lag_name)
40+
{
41+
if (has_key(lag_name))
42+
{
43+
SWSS_LOG_DEBUG("The LAG '%s' was already added. Skip adding it.", lag_name.c_str());
44+
return true;
45+
}
46+
else
47+
{
48+
auto tdc = teamdctl_alloc();
49+
if (!tdc)
50+
{
51+
SWSS_LOG_ERROR("Can't allocate memory for teamdctl handler. LAG='%s'", lag_name.c_str());
52+
return false;
53+
}
54+
55+
int err = teamdctl_connect(tdc, lag_name.c_str(), nullptr, nullptr);
56+
if (err)
57+
{
58+
SWSS_LOG_ERROR("Can't connect to teamd LAG='%s', error='%s'", lag_name.c_str(), strerror(-err));
59+
teamdctl_free(tdc);
60+
return false;
61+
}
62+
m_handlers.emplace(lag_name, tdc);
63+
SWSS_LOG_NOTICE("The LAG '%s' has been added.", lag_name.c_str());
64+
}
65+
66+
return true;
67+
}
68+
69+
///
70+
/// Removes a LAG interface with lag_name from the manager
71+
/// This method deallocates teamd structures
72+
/// @param lag_name a name for LAG interface
73+
/// @return true if the lag was removed successfully, false otherwise
74+
///
75+
bool TeamdCtlMgr::remove_lag(const std::string & lag_name)
76+
{
77+
if (has_key(lag_name))
78+
{
79+
auto tdc = m_handlers[lag_name];
80+
teamdctl_disconnect(tdc);
81+
teamdctl_free(tdc);
82+
m_handlers.erase(lag_name);
83+
SWSS_LOG_NOTICE("The LAG '%s' has been removed.", lag_name.c_str());
84+
}
85+
else
86+
{
87+
SWSS_LOG_WARN("The LAG '%s' hasn't been added. Can't remove it", lag_name.c_str());
88+
}
89+
return true;
90+
}
91+
92+
///
93+
/// Get json dump from teamd for LAG interface with name lag_name
94+
/// @param lag_name a name for LAG interface
95+
/// @return a pair. First element of the pair is true, if the method is successful
96+
/// false otherwise. If the first element is true, the second element has a dump
97+
/// otherwise the second element is an empty string
98+
///
99+
TeamdCtlDump TeamdCtlMgr::get_dump(const std::string & lag_name)
100+
{
101+
TeamdCtlDump res = { false, "" };
102+
if (has_key(lag_name))
103+
{
104+
auto tdc = m_handlers[lag_name];
105+
char * dump;
106+
int r = teamdctl_state_get_raw_direct(tdc, &dump);
107+
if (r == 0)
108+
{
109+
res = { true, std::string(dump) };
110+
}
111+
else
112+
{
113+
SWSS_LOG_ERROR("Can't get dump for LAG '%s'. Skipping", lag_name.c_str());
114+
}
115+
}
116+
else
117+
{
118+
SWSS_LOG_ERROR("Can't update state. LAG not found. LAG='%s'", lag_name.c_str());
119+
}
120+
121+
return res;
122+
}
123+
124+
///
125+
/// Get dumps for all registered LAG interfaces
126+
/// @return vector of pairs. Each pair first value is a name of LAG, second value is a dump
127+
///
128+
TeamdCtlDumps TeamdCtlMgr::get_dumps()
129+
{
130+
TeamdCtlDumps res;
131+
132+
for (const auto & p: m_handlers)
133+
{
134+
const auto & lag_name = p.first;
135+
const auto & result = get_dump(lag_name);
136+
const auto & status = result.first;
137+
const auto & dump = result.second;
138+
if (status)
139+
{
140+
res.push_back({ lag_name, dump });
141+
}
142+
}
143+
144+
return res;
145+
}
146+

tlm_teamd/teamdctl_mgr.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
#include <unordered_map>
6+
7+
#include <teamdctl.h>
8+
9+
using TeamdCtlDump = std::pair<bool, std::string>;
10+
using TeamdCtlDumpsEntry = std::pair<std::string, std::string>;
11+
using TeamdCtlDumps = std::vector<TeamdCtlDumpsEntry>;
12+
13+
class TeamdCtlMgr
14+
{
15+
public:
16+
TeamdCtlMgr() = default;
17+
~TeamdCtlMgr();
18+
bool add_lag(const std::string & kag_name);
19+
bool remove_lag(const std::string & kag_name);
20+
TeamdCtlDump get_dump(const std::string & lag_name);
21+
TeamdCtlDumps get_dumps();
22+
23+
private:
24+
bool has_key(const std::string & lag_name) const;
25+
26+
std::unordered_map<std::string, struct teamdctl*> m_handlers;
27+
};

0 commit comments

Comments
 (0)