Skip to content

Commit 66e4c51

Browse files
Elad RazShuotian Cheng
Elad Raz
authored and
Shuotian Cheng
committed
teamsyncd: Initial version
The teamsyncd listens to RTM_NEWLINK and RTM_DELLINK and creates or delete entries at the LAG_TABLE:<team0>. Example: 127.0.0.1:6379> HGETALL "LAG_TABLE:team0" 1) "admin_status" 2) "down" 3) "oper_status" 4) "down" 5) "mtu" 6) "1500" In addition for each team device, the teamsyncd listens to team events and reflects the LAG ports into the redis under: LAG_TABLE:<team0>:port For example: 127.0.0.1:6379> HGETALL "LAG_TABLE:team0:veth0" 1) "linkup" 2) "down" 3) "speed" 4) "0Mbit" 5) "duplex" 6) "half" Signed-off-by: Elad Raz <eladr@mellanox.com>
1 parent ea9b9a3 commit 66e4c51

7 files changed

+321
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ deps/
4040

4141
# Executables #
4242
###############
43+
teamsyncd/teamsyncd
4344
fpmsyncd/fpmsyncd
4445
intfsyncd/intfsyncd
4546
neighsyncd/neighsyncd

Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig
1+
SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd teamsyncd orchagent swssconfig

configure.ac

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ AC_CONFIG_FILES([
3434
neighsyncd/Makefile
3535
intfsyncd/Makefile
3636
portsyncd/Makefile
37+
teamsyncd/Makefile
3738
swssconfig/Makefile
3839
])
3940

teamsyncd/Makefile.am

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
INCLUDES = -I $(top_srcdir)
2+
3+
bin_PROGRAMS = teamsyncd
4+
5+
if DEBUG
6+
DBGFLAGS = -ggdb -DDEBUG
7+
else
8+
DBGFLAGS = -g
9+
endif
10+
11+
teamsyncd_SOURCES = teamsyncd.cpp teamsync.cpp
12+
13+
teamsyncd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
14+
teamsyncd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
15+
teamsyncd_LDADD = -lnl-3 -lnl-route-3 -lhiredis -lswsscommon -lteam

teamsyncd/teamsync.cpp

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#include <string.h>
2+
#include <errno.h>
3+
#include <system_error>
4+
#include <sys/socket.h>
5+
#include <linux/if.h>
6+
#include <netlink/route/link.h>
7+
#include "logger.h"
8+
#include "netmsg.h"
9+
#include "dbconnector.h"
10+
#include "producertable.h"
11+
#include "scheme.h"
12+
#include "teamsync.h"
13+
14+
using namespace std;
15+
using namespace swss;
16+
17+
/* Taken from drivers/net/team/team.c */
18+
#define TEAM_DRV_NAME "team"
19+
20+
TeamSync::TeamSync(DBConnector *db, Select *select) :
21+
m_select(select),
22+
m_lagTable(db, APP_LAG_TABLE_NAME)
23+
{
24+
}
25+
26+
void TeamSync::onMsg(int nlmsg_type, struct nl_object *obj)
27+
{
28+
struct rtnl_link *link = (struct rtnl_link *)obj;
29+
if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_DELLINK))
30+
return;
31+
32+
string lagName = rtnl_link_get_name(link);
33+
/* Listens to LAG messages */
34+
char *type = rtnl_link_get_type(link);
35+
if (!type || (strcmp(type, TEAM_DRV_NAME) != 0))
36+
return;
37+
38+
bool tracked = m_teamPorts.find(lagName) != m_teamPorts.end();
39+
40+
if ((nlmsg_type == RTM_DELLINK) && tracked)
41+
{
42+
/* Remove LAG ports and delete LAG */
43+
removeLag(lagName);
44+
return;
45+
}
46+
47+
if ((nlmsg_type == RTM_NEWLINK) && tracked)
48+
return;
49+
50+
/*
51+
* New LAG was dedcated for the first time. Sync admin and oper state since
52+
* portsyncd reflects only changes
53+
*/
54+
addLag(lagName, rtnl_link_get_ifindex(link),
55+
rtnl_link_get_flags(link) & IFF_UP,
56+
rtnl_link_get_flags(link) & IFF_LOWER_UP,
57+
rtnl_link_get_mtu(link));
58+
}
59+
60+
void TeamSync::addLag(const string &lagName, int ifindex, bool admin_state,
61+
bool oper_state, unsigned int mtu)
62+
{
63+
/* First add the LAG itself */
64+
std::vector<FieldValueTuple> fvVector;
65+
FieldValueTuple a("admin_status", admin_state ? "up" : "down");
66+
FieldValueTuple o("oper_status", oper_state ? "up" : "down");
67+
FieldValueTuple m("mtu", to_string(mtu));
68+
fvVector.push_back(a);
69+
fvVector.push_back(o);
70+
fvVector.push_back(m);
71+
m_lagTable.set(lagName, fvVector);
72+
73+
/* Start adding ports to LAG */
74+
TeamPortSync *sync = new TeamPortSync(lagName, ifindex, &m_lagTable);
75+
m_select->addSelectable(sync);
76+
m_teamPorts[lagName] = shared_ptr<TeamPortSync>(sync);
77+
}
78+
79+
void TeamSync::removeLag(const string &lagName)
80+
{
81+
m_select->removeSelectable(m_teamPorts[lagName].get());
82+
m_teamPorts.erase(lagName);
83+
m_lagTable.del(lagName);
84+
}
85+
86+
const struct team_change_handler TeamSync::TeamPortSync::gPortChangeHandler = {
87+
.func = TeamSync::TeamPortSync::teamdHandler,
88+
.type_mask = TEAM_PORT_CHANGE
89+
};
90+
91+
TeamSync::TeamPortSync::TeamPortSync(const string &lagName, int ifindex,
92+
ProducerTable *lagTable) :
93+
m_lagTable(lagTable),
94+
m_lagName(lagName),
95+
m_ifindex(ifindex)
96+
{
97+
m_team = team_alloc();
98+
if (!m_team)
99+
{
100+
SWSS_LOG_ERROR("Unable to allocated team socket");
101+
throw system_error(make_error_code(errc::address_not_available),
102+
"Unable to allocated team socket");
103+
}
104+
105+
int err = team_init(m_team, ifindex);
106+
if (err) {
107+
team_free(m_team);
108+
m_team = NULL;
109+
SWSS_LOG_ERROR("Unable to init team socket");
110+
throw system_error(make_error_code(errc::address_not_available),
111+
"Unable to init team socket");
112+
}
113+
114+
err = team_change_handler_register(m_team, &gPortChangeHandler, this);
115+
if (err) {
116+
team_free(m_team);
117+
m_team = NULL;
118+
SWSS_LOG_ERROR("Unable to register port change event");
119+
throw system_error(make_error_code(errc::address_not_available),
120+
"Unable to register port change event");
121+
}
122+
123+
onPortChange(true);
124+
}
125+
126+
TeamSync::TeamPortSync::~TeamPortSync()
127+
{
128+
if (m_team)
129+
{
130+
team_change_handler_unregister(m_team, &gPortChangeHandler, this);
131+
team_free(m_team);
132+
}
133+
}
134+
135+
int TeamSync::TeamPortSync::onPortChange(bool isInit)
136+
{
137+
struct team_port *port;
138+
team_for_each_port(port, m_team)
139+
{
140+
if (isInit || team_is_port_changed(port))
141+
{
142+
string key = m_lagName;
143+
key += ":";
144+
uint32_t ifindex = team_get_port_ifindex(port);
145+
char ifname[MAX_IFNAME + 1] = {0};
146+
key += team_ifindex2ifname(m_team, ifindex, ifname, MAX_IFNAME);
147+
148+
if (team_is_port_removed(port))
149+
{
150+
m_lagTable->del(key);
151+
} else
152+
{
153+
std::vector<FieldValueTuple> fvVector;
154+
FieldValueTuple l("linkup", team_is_port_link_up(port) ? "up" : "down");
155+
FieldValueTuple s("speed", to_string(team_get_port_speed(port)) + "Mbit");
156+
FieldValueTuple d("duplex", team_get_port_duplex(port) ? "full" : "half");
157+
fvVector.push_back(l);
158+
fvVector.push_back(s);
159+
fvVector.push_back(d);
160+
m_lagTable->set(key, fvVector);
161+
}
162+
}
163+
}
164+
return 0;
165+
}
166+
167+
int TeamSync::TeamPortSync::teamdHandler(struct team_handle *team, void *arg,
168+
team_change_type_mask_t type_mask)
169+
{
170+
return ((TeamSync::TeamPortSync *)arg)->onPortChange(false);
171+
}
172+
173+
void TeamSync::TeamPortSync::addFd(fd_set *fd)
174+
{
175+
FD_SET(team_get_event_fd(m_team), fd);
176+
}
177+
178+
bool TeamSync::TeamPortSync::isMe(fd_set *fd)
179+
{
180+
return FD_ISSET(team_get_event_fd(m_team), fd);
181+
}
182+
183+
int TeamSync::TeamPortSync::readCache()
184+
{
185+
return NODATA;
186+
}
187+
188+
void TeamSync::TeamPortSync::readMe()
189+
{
190+
team_handle_events(m_team);
191+
}

teamsyncd/teamsync.h

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#ifndef __TEAMSYNC__
2+
#define __TEAMSYNC__
3+
4+
#include <map>
5+
#include <string>
6+
#include <memory>
7+
#include "dbconnector.h"
8+
#include "producertable.h"
9+
#include "selectable.h"
10+
#include "select.h"
11+
#include "netmsg.h"
12+
#include <team.h>
13+
14+
namespace swss {
15+
16+
class TeamSync : public NetMsg
17+
{
18+
public:
19+
TeamSync(DBConnector *db, Select *select);
20+
21+
/*
22+
* Listens to RTM_NEWLINK and RTM_DELLINK to undestand if there is a new
23+
* team device
24+
*/
25+
virtual void onMsg(int nlmsg_type, struct nl_object *obj);
26+
27+
class TeamPortSync : public Selectable
28+
{
29+
public:
30+
enum { MAX_IFNAME = 64 };
31+
TeamPortSync(const std::string &lagName, int ifindex,
32+
ProducerTable *lagTable);
33+
~TeamPortSync();
34+
35+
virtual void addFd(fd_set *fd);
36+
virtual bool isMe(fd_set *fd);
37+
virtual int readCache();
38+
virtual void readMe();
39+
40+
protected:
41+
int onPortChange(bool isInit);
42+
static int teamdHandler(struct team_handle *th, void *arg,
43+
team_change_type_mask_t type_mask);
44+
static const struct team_change_handler gPortChangeHandler;
45+
private:
46+
ProducerTable *m_lagTable;
47+
struct team_handle *m_team;
48+
std::string m_lagName;
49+
int m_ifindex;
50+
};
51+
52+
protected:
53+
void addLag(const std::string &lagName, int ifindex, bool admin_state,
54+
bool oper_state, unsigned int mtu);
55+
void removeLag(const std::string &lagName);
56+
57+
private:
58+
Select *m_select;
59+
ProducerTable m_lagTable;
60+
std::map<std::string, std::shared_ptr<TeamPortSync> > m_teamPorts;
61+
};
62+
63+
}
64+
65+
#endif

teamsyncd/teamsyncd.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <iostream>
2+
#include <team.h>
3+
#include "logger.h"
4+
#include "select.h"
5+
#include "netdispatcher.h"
6+
#include "netlink.h"
7+
#include "teamsync.h"
8+
9+
using namespace std;
10+
using namespace swss;
11+
12+
int main(int argc, char **argv)
13+
{
14+
DBConnector db(APPL_DB, "localhost", 6379, 0);
15+
Select s;
16+
TeamSync sync(&db, &s);
17+
18+
NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, &sync);
19+
NetDispatcher::getInstance().registerMessageHandler(RTM_DELLINK, &sync);
20+
21+
while (1)
22+
{
23+
try
24+
{
25+
NetLink netlink;
26+
27+
netlink.registerGroup(RTNLGRP_LINK);
28+
cout << "Listens to teamd events..." << endl;
29+
netlink.dumpRequest(RTM_GETLINK);
30+
31+
s.addSelectable(&netlink);
32+
while (true)
33+
{
34+
Selectable *temps;
35+
int tempfd;
36+
s.select(&temps, &tempfd);
37+
}
38+
}
39+
catch (...)
40+
{
41+
cout << "Exception had been thrown in deamon" << endl;
42+
return 0;
43+
}
44+
}
45+
46+
return 1;
47+
}

0 commit comments

Comments
 (0)