Skip to content

Commit 38739fb

Browse files
author
Ashish Singh
committed
[Link Event Damping] Add tracker to track the selectable timers used by
link event damper. - Link event damper running on each port will have its own SelectableTimer. This class helps create a mapping of SelectableTimer and object that created the SelectableTimer so that when timer is fired, proper EventHandler object can be invoked. HLD: sonic-net/SONiC#1071
1 parent 92da5b3 commit 38739fb

7 files changed

Lines changed: 344 additions & 0 deletions

File tree

syncd/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ libSyncd_a_SOURCES = \
4343
SaiObj.cpp \
4444
SaiSwitch.cpp \
4545
SaiSwitchInterface.cpp \
46+
SelectablesTracker.cpp \
4647
ServiceMethodTable.cpp \
4748
SingleReiniter.cpp \
4849
SwitchNotifications.cpp \

syncd/SelectablesTracker.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#include "SelectablesTracker.h"
2+
3+
#include "swss/logger.h"
4+
5+
using namespace syncd;
6+
7+
bool SelectablesTracker::addSelectableToTracker(
8+
_In_ swss::Selectable *selectable,
9+
_In_ SelectableEventHandler *eventHandler)
10+
{
11+
SWSS_LOG_ENTER();
12+
13+
if (selectable == nullptr)
14+
{
15+
SWSS_LOG_ERROR("Invalid Selectable:Selectable is NULL.");
16+
17+
return false;
18+
}
19+
20+
int fd = selectable->getFd();
21+
if (eventHandler == nullptr)
22+
{
23+
SWSS_LOG_ERROR("Event handler for Selectable with fd: %d is NULL.", fd);
24+
25+
return false;
26+
}
27+
28+
if (m_selectableFdToEventHandlerMap.count(fd) != 0)
29+
{
30+
SWSS_LOG_ERROR("Selectable with fd %d is already in use.", fd);
31+
32+
return false;
33+
}
34+
35+
SWSS_LOG_INFO("Adding the Selectable with fd: %d.", fd);
36+
m_selectableFdToEventHandlerMap[fd] = eventHandler;
37+
38+
return true;
39+
}
40+
41+
bool SelectablesTracker::removeSelectableFromTracker(
42+
_In_ swss::Selectable *selectable)
43+
{
44+
SWSS_LOG_ENTER();
45+
46+
if (selectable == nullptr)
47+
{
48+
SWSS_LOG_ERROR("Invalid Selectable:Selectable is NULL.");
49+
50+
return false;
51+
}
52+
53+
int fd = selectable->getFd();
54+
55+
SWSS_LOG_INFO("Removing the Selectable with fd: %d.", fd);
56+
if (m_selectableFdToEventHandlerMap.erase(fd) == 0)
57+
{
58+
SWSS_LOG_ERROR("Selectable with fd %d is not present in the map!", fd);
59+
60+
return false;
61+
}
62+
63+
return true;
64+
}
65+
66+
bool SelectablesTracker::selectableIsTracked(
67+
_In_ swss::Selectable *selectable)
68+
{
69+
SWSS_LOG_ENTER();
70+
71+
if ((selectable == nullptr) ||
72+
(m_selectableFdToEventHandlerMap.count(selectable->getFd()) == 0))
73+
{
74+
return false;
75+
}
76+
77+
return true;
78+
}
79+
80+
SelectableEventHandler *SelectablesTracker::getEventHandlerForSelectable(
81+
_In_ swss::Selectable *selectable)
82+
{
83+
SWSS_LOG_ENTER();
84+
85+
if (selectable == nullptr)
86+
{
87+
SWSS_LOG_ERROR("Invalid Selectable:Selectable is NULL.");
88+
89+
return nullptr;
90+
}
91+
92+
int fd = selectable->getFd();
93+
auto it = m_selectableFdToEventHandlerMap.find(fd);
94+
95+
if (it == m_selectableFdToEventHandlerMap.end())
96+
{
97+
SWSS_LOG_ERROR("Selectable with fd %d is not present in the map!", fd);
98+
99+
return nullptr;
100+
}
101+
102+
return it->second;
103+
}

syncd/SelectablesTracker.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include <unordered_map>
4+
5+
#include "SelectableEventHandler.h"
6+
#include "swss/sal.h"
7+
#include "swss/selectable.h"
8+
#include "swss/selectabletimer.h"
9+
10+
namespace syncd
11+
{
12+
// This class keeps track of Selectable being used by an entity and their
13+
// corresponding EventHandler objects.
14+
class SelectablesTracker
15+
{
16+
private:
17+
18+
// Not copyable or movable.
19+
SelectablesTracker(const SelectablesTracker &) = delete;
20+
SelectablesTracker(SelectablesTracker &&) = delete;
21+
SelectablesTracker &operator=(const SelectablesTracker &) = delete;
22+
SelectablesTracker &operator=(SelectablesTracker &&) = delete;
23+
24+
public:
25+
26+
SelectablesTracker() = default;
27+
28+
virtual ~SelectablesTracker() = default;
29+
30+
// Adds the mapping of Selectable and it's corresponding EventHandler object.
31+
virtual bool addSelectableToTracker(
32+
_In_ swss::Selectable *selectable,
33+
_In_ SelectableEventHandler *eventHandler);
34+
35+
// Removes a Selectable from the map.
36+
virtual bool removeSelectableFromTracker(
37+
_In_ swss::Selectable *selectable);
38+
39+
// Checks if Selectable is present in the tracker map.
40+
virtual bool selectableIsTracked(
41+
_In_ swss::Selectable *selectable);
42+
43+
// Gets the EventHandler for a Selectable.
44+
virtual SelectableEventHandler *getEventHandlerForSelectable(
45+
_In_ swss::Selectable *selectable);
46+
47+
private:
48+
49+
using SelectableFdToEventHandlerMap = std::unordered_map<int, SelectableEventHandler *>;
50+
51+
SelectableFdToEventHandlerMap m_selectableFdToEventHandlerMap;
52+
};
53+
54+
} // namespace syncd

tests/aspell.en.pws

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ config
149149
const
150150
CONST
151151
consts
152+
copyable
152153
counterName
153154
countOnly
154155
cout

unittest/syncd/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ tests_SOURCES = main.cpp \
1717
TestNotificationHandler.cpp \
1818
TestMdioIpcServer.cpp \
1919
TestPortStateChangeHandler.cpp \
20+
TestSelectablesTracker.cpp \
2021
TestVendorSai.cpp
2122

2223
tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "SelectablesTracker.h"
4+
#include "gmock/gmock.h"
5+
6+
namespace syncd
7+
{
8+
9+
class MockSelectablesTracker : public SelectablesTracker
10+
{
11+
public:
12+
13+
MockSelectablesTracker() : SelectablesTracker() {}
14+
15+
~MockSelectablesTracker() override {}
16+
17+
MOCK_METHOD2(addSelectableToTracker, bool(swss::Selectable *selectable,
18+
SelectableEventHandler *eventHandler) override);
19+
20+
MOCK_METHOD1(removeSelectableFromTracker,
21+
bool(swss::Selectable *selectable) override);
22+
};
23+
} // namespace syncd
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include <gtest/gtest.h>
2+
3+
#include "SelectablesTracker.h"
4+
5+
using namespace syncd;
6+
7+
class SelectableEventHandlerTestHelper : public SelectableEventHandler
8+
{
9+
public:
10+
11+
SelectableEventHandlerTestHelper() {}
12+
~SelectableEventHandlerTestHelper() {}
13+
14+
void handleSelectableEvent() {}
15+
};
16+
17+
class SelectablesTrackerTest : public ::testing::Test
18+
{
19+
public:
20+
21+
SelectablesTrackerTest() {}
22+
23+
SelectablesTracker m_selectablesTracker_;
24+
};
25+
26+
TEST_F(SelectablesTrackerTest, AddSelectableFailsIfSelectableNull)
27+
{
28+
SelectableEventHandlerTestHelper eventHandler;
29+
30+
EXPECT_FALSE(m_selectablesTracker_.addSelectableToTracker(
31+
/*selectable=*/nullptr, (SelectableEventHandler *)&eventHandler));
32+
}
33+
34+
TEST_F(SelectablesTrackerTest, AddSelectableFailsIfEventHandlerNull)
35+
{
36+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
37+
38+
EXPECT_FALSE(m_selectablesTracker_.addSelectableToTracker(
39+
(swss::Selectable *)&timer, /*eventHandler=*/nullptr));
40+
}
41+
42+
TEST_F(SelectablesTrackerTest, AddSelectableSucceeds)
43+
{
44+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
45+
SelectableEventHandlerTestHelper eventHandler;
46+
47+
EXPECT_TRUE(m_selectablesTracker_.addSelectableToTracker(
48+
(swss::Selectable *)&timer, (SelectableEventHandler *)&eventHandler));
49+
}
50+
51+
TEST_F(SelectablesTrackerTest, AddSelectableFailsIfSelectableExists)
52+
{
53+
// Add a selectable timer to tracker.
54+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
55+
SelectableEventHandlerTestHelper eventHandler;
56+
57+
EXPECT_TRUE(m_selectablesTracker_.addSelectableToTracker(
58+
(swss::Selectable *)&timer, (SelectableEventHandler *)&eventHandler));
59+
60+
// Adding the same selectable timer to tracker should fail.
61+
SelectableEventHandlerTestHelper eventHandler2;
62+
EXPECT_FALSE(m_selectablesTracker_.addSelectableToTracker(
63+
(swss::Selectable *)&timer, (SelectableEventHandler *)&eventHandler2));
64+
}
65+
66+
TEST_F(SelectablesTrackerTest, RemoveSelectableFailsIfSelectableNull)
67+
{
68+
EXPECT_FALSE(
69+
m_selectablesTracker_.removeSelectableFromTracker(/*selectable=*/nullptr));
70+
}
71+
72+
TEST_F(SelectablesTrackerTest, RemoveSelectableFailsIfSelectableNotExist)
73+
{
74+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
75+
76+
EXPECT_FALSE(m_selectablesTracker_.removeSelectableFromTracker(
77+
(swss::Selectable *)&timer));
78+
}
79+
80+
TEST_F(SelectablesTrackerTest, RemoveSelectableSucceeds)
81+
{
82+
// Add a selectable timer.
83+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
84+
SelectableEventHandlerTestHelper eventHandler;
85+
86+
EXPECT_TRUE(m_selectablesTracker_.addSelectableToTracker(
87+
(swss::Selectable *)&timer, (SelectableEventHandler *)&eventHandler));
88+
89+
// Remove the selectable timer just added in tracker.
90+
EXPECT_TRUE(m_selectablesTracker_.removeSelectableFromTracker(
91+
(swss::Selectable *)&timer));
92+
93+
// Removing the selectable timer again should fail.
94+
EXPECT_FALSE(m_selectablesTracker_.removeSelectableFromTracker(
95+
(swss::Selectable *)&timer));
96+
}
97+
98+
TEST_F(SelectablesTrackerTest, NullptrSelectableIsNotTracked)
99+
{
100+
EXPECT_FALSE(
101+
m_selectablesTracker_.selectableIsTracked(/*selectable=*/nullptr));
102+
}
103+
104+
TEST_F(SelectablesTrackerTest, SelectableIsNotTracked)
105+
{
106+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
107+
EXPECT_FALSE(
108+
m_selectablesTracker_.selectableIsTracked((swss::Selectable *)&timer));
109+
}
110+
111+
TEST_F(SelectablesTrackerTest, SelectableIsTracked)
112+
{
113+
// Add the Selectable in the tracker.
114+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
115+
SelectableEventHandlerTestHelper eventHandler;
116+
117+
EXPECT_TRUE(m_selectablesTracker_.addSelectableToTracker(
118+
(swss::Selectable *)&timer, (SelectableEventHandler *)&eventHandler));
119+
120+
// Verify the Selectable in the tracker.
121+
EXPECT_TRUE(
122+
m_selectablesTracker_.selectableIsTracked((swss::Selectable *)&timer));
123+
124+
// Remove the Selectable from tracker.
125+
EXPECT_TRUE(m_selectablesTracker_.removeSelectableFromTracker(
126+
(swss::Selectable *)&timer));
127+
128+
// Check the Selectable in tracker again, this time it should fail.
129+
EXPECT_FALSE(
130+
m_selectablesTracker_.selectableIsTracked((swss::Selectable *)&timer));
131+
}
132+
133+
TEST_F(SelectablesTrackerTest, GetEventHandlerFailsIfSelectableNull)
134+
{
135+
EXPECT_EQ(
136+
m_selectablesTracker_.getEventHandlerForSelectable(/*selectable=*/nullptr),
137+
nullptr);
138+
}
139+
140+
TEST_F(SelectablesTrackerTest, GetEventHandlerFailsIfSelectableNotExist)
141+
{
142+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
143+
EXPECT_EQ(m_selectablesTracker_.getEventHandlerForSelectable(
144+
(swss::Selectable *)&timer),
145+
nullptr);
146+
}
147+
148+
TEST_F(SelectablesTrackerTest, GetEventHandlerSucceeds)
149+
{
150+
// Add a selectable timer.
151+
swss::SelectableTimer timer(/*interval=*/{.tv_sec = 10, .tv_nsec = 20});
152+
SelectableEventHandlerTestHelper eventHandler;
153+
154+
EXPECT_TRUE(m_selectablesTracker_.addSelectableToTracker(
155+
(swss::Selectable *)&timer, (SelectableEventHandler *)&eventHandler));
156+
157+
// Get the event handler for the selectable timer.
158+
EXPECT_EQ(m_selectablesTracker_.getEventHandlerForSelectable(
159+
(swss::Selectable *)&timer),
160+
(SelectableEventHandler *)&eventHandler);
161+
}

0 commit comments

Comments
 (0)