Skip to content

Commit a1530e3

Browse files
pavel-shirshovPS
and
PS
authored
[tlm_teamd]: Try to add LAG again, when teamd is not ready first time (sonic-net#1347)
* Postpone add LAG operation, when can't add right away * Set empty log function for teamdctl library * Return empty list if there is no ports in the PortChannel Co-authored-by: PS <ps@cs.com>
1 parent a9479e6 commit a1530e3

File tree

4 files changed

+97
-20
lines changed

4 files changed

+97
-20
lines changed

tlm_teamd/main.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ int main()
107107
}
108108
else if (res == swss::Select::TIMEOUT)
109109
{
110+
teamdctl_mgr.process_add_queue();
110111
values_store.update(teamdctl_mgr.get_dumps());
111112
}
112113
else

tlm_teamd/teamdctl_mgr.cpp

+88-17
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
11
#include <cstring>
2+
#include <algorithm>
23

34
#include <logger.h>
45

56
#include "teamdctl_mgr.h"
67

8+
///
9+
/// Custom function for libteamdctl logger. IT is empty to prevent libteamdctl to spam us with the error messages
10+
/// @param tdc teamdctl descriptor
11+
/// @param priority priority of the message
12+
/// @param file file where error was raised
13+
/// @param line line in the file where error was raised
14+
/// @param fn function where the error was raised
15+
/// @param format format of the error message
16+
/// @param args arguments of the error message
17+
void teamdctl_log_function(struct teamdctl *tdc, int priority,
18+
const char *file, int line,
19+
const char *fn, const char *format,
20+
va_list args)
21+
{
22+
23+
}
24+
25+
726
///
827
/// The destructor clean up handlers to teamds
928
///
@@ -31,10 +50,11 @@ bool TeamdCtlMgr::has_key(const std::string & lag_name) const
3150
}
3251

3352
///
34-
/// Adds a LAG interface with lag_name to the manager
35-
/// This method allocates structures to connect to teamd
53+
/// Public method to add a LAG interface with lag_name to the manager
54+
/// This method tries to add. If the method can't add the LAG interface,
55+
/// this action will be postponed.
3656
/// @param lag_name a name for LAG interface
37-
/// @return true if the lag was added successfully, false otherwise
57+
/// @return true if the lag was added or postponed successfully, false otherwise
3858
///
3959
bool TeamdCtlMgr::add_lag(const std::string & lag_name)
4060
{
@@ -43,26 +63,51 @@ bool TeamdCtlMgr::add_lag(const std::string & lag_name)
4363
SWSS_LOG_DEBUG("The LAG '%s' was already added. Skip adding it.", lag_name.c_str());
4464
return true;
4565
}
46-
else
66+
return try_add_lag(lag_name);
67+
}
68+
69+
///
70+
/// Try to adds a LAG interface with lag_name to the manager
71+
/// This method allocates structures to connect to teamd
72+
/// if the method can't add, it will retry to add next time
73+
/// @param lag_name a name for LAG interface
74+
/// @return true if the lag was added successfully, false otherwise
75+
///
76+
bool TeamdCtlMgr::try_add_lag(const std::string & lag_name)
77+
{
78+
if (m_lags_to_add.find(lag_name) == m_lags_to_add.end())
4779
{
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-
}
80+
m_lags_to_add[lag_name] = 0;
81+
}
5482

55-
int err = teamdctl_connect(tdc, lag_name.c_str(), nullptr, nullptr);
56-
if (err)
83+
int attempt = m_lags_to_add[lag_name];
84+
85+
auto tdc = teamdctl_alloc();
86+
if (!tdc)
87+
{
88+
SWSS_LOG_ERROR("Can't allocate memory for teamdctl handler. LAG='%s'. attempt=%d", lag_name.c_str(), attempt);
89+
m_lags_to_add[lag_name]++;
90+
return false;
91+
}
92+
93+
teamdctl_set_log_fn(tdc, &teamdctl_log_function);
94+
95+
int err = teamdctl_connect(tdc, lag_name.c_str(), nullptr, nullptr);
96+
if (err)
97+
{
98+
if (attempt != 0)
5799
{
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;
100+
SWSS_LOG_WARN("Can't connect to teamd LAG='%s', error='%s'. attempt=%d", lag_name.c_str(), strerror(-err), attempt);
61101
}
62-
m_handlers.emplace(lag_name, tdc);
63-
SWSS_LOG_NOTICE("The LAG '%s' has been added.", lag_name.c_str());
102+
teamdctl_free(tdc);
103+
m_lags_to_add[lag_name]++;
104+
return false;
64105
}
65106

107+
m_handlers.emplace(lag_name, tdc);
108+
m_lags_to_add.erase(lag_name);
109+
SWSS_LOG_NOTICE("The LAG '%s' has been added.", lag_name.c_str());
110+
66111
return true;
67112
}
68113

@@ -82,13 +127,39 @@ bool TeamdCtlMgr::remove_lag(const std::string & lag_name)
82127
m_handlers.erase(lag_name);
83128
SWSS_LOG_NOTICE("The LAG '%s' has been removed.", lag_name.c_str());
84129
}
130+
else if (m_lags_to_add.find(lag_name) != m_lags_to_add.end())
131+
{
132+
m_lags_to_add.erase(lag_name);
133+
SWSS_LOG_DEBUG("The LAG '%s' has been removed from adding queue.", lag_name.c_str());
134+
}
85135
else
86136
{
87137
SWSS_LOG_WARN("The LAG '%s' hasn't been added. Can't remove it", lag_name.c_str());
88138
}
89139
return true;
90140
}
91141

142+
///
143+
/// Process the queue with postponed add operations for LAG.
144+
///
145+
void TeamdCtlMgr::process_add_queue()
146+
{
147+
std::vector<std::string> lag_names_to_add;
148+
std::transform(m_lags_to_add.begin(), m_lags_to_add.end(), lag_names_to_add.begin(), [](auto pair) { return pair.first; });
149+
for (const auto lag_name: lag_names_to_add)
150+
{
151+
bool result = try_add_lag(lag_name);
152+
if (!result)
153+
{
154+
if (m_lags_to_add[lag_name] == TeamdCtlMgr::max_attempts_to_add)
155+
{
156+
SWSS_LOG_ERROR("Can't connect to teamd after %d attempts. LAG '%s'", TeamdCtlMgr::max_attempts_to_add, lag_name.c_str());
157+
m_lags_to_add.erase(lag_name);
158+
}
159+
}
160+
}
161+
}
162+
92163
///
93164
/// Get json dump from teamd for LAG interface with name lag_name
94165
/// @param lag_name a name for LAG interface

tlm_teamd/teamdctl_mgr.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ class TeamdCtlMgr
1515
public:
1616
TeamdCtlMgr() = default;
1717
~TeamdCtlMgr();
18-
bool add_lag(const std::string & kag_name);
19-
bool remove_lag(const std::string & kag_name);
18+
bool add_lag(const std::string & lag_name);
19+
bool remove_lag(const std::string & lag_name);
20+
void process_add_queue();
2021
TeamdCtlDump get_dump(const std::string & lag_name);
2122
TeamdCtlDumps get_dumps();
2223

2324
private:
2425
bool has_key(const std::string & lag_name) const;
26+
bool try_add_lag(const std::string & lag_name);
2527

2628
std::unordered_map<std::string, struct teamdctl*> m_handlers;
29+
std::unordered_map<std::string, int> m_lags_to_add;
30+
31+
const int max_attempts_to_add = 10;
2732
};

tlm_teamd/values_store.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ std::vector<std::string> ValuesStore::get_ports(json_t * root)
1616
int err = json_unpack(root, "{s:o}", "ports", &ports);
1717
if (err != 0)
1818
{
19-
throw std::runtime_error("Can't find 'ports' in the json dump object");
19+
return result;
2020
}
2121

2222
const char * key;

0 commit comments

Comments
 (0)