diff --git a/doc/swss-schema.md b/doc/swss-schema.md index 372240af1063..898b3ea5a69e 100644 --- a/doc/swss-schema.md +++ b/doc/swss-schema.md @@ -124,7 +124,7 @@ For example (reorder output) speed key = LAG_TABLE:lagname:ifname ; physical port member of LAG, fk to PORT_TABLE:ifname - oper_status = "down" / "up" ; Oper status (physical + 802.3ad state) + status = "enabled" / "disabled" ; selected + distributing/collecting (802.3ad) speed = ; set by LAG application, must match PORT_TABLE.duplex duplex = ; set by LAG application, must match PORT_TABLE.duplex @@ -142,8 +142,8 @@ In addition for each team device, the teamsyncd listens to team events and reflects the LAG ports into the redis under: `LAG_TABLE::port` 127.0.0.1:6379> HGETALL "LAG_TABLE:team0:veth0" - 1) "linkup" - 2) "down" + 1) "status" + 2) "disabled" 3) "speed" 4) "0Mbit" 5) "duplex" diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 06dd80fc510d..8f960e1dafe9 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -565,7 +565,7 @@ void PortsOrch::doLagTask(Consumer &consumer) it = consumer.m_toSync.erase(it); } } - /* Manipulate member */ + /* Manipulate a LAG member */ else { assert(m_portList.find(lag_alias) != m_portList.end()); @@ -573,17 +573,18 @@ void PortsOrch::doLagTask(Consumer &consumer) getPort(lag_alias, lag); getPort(port_alias, port); + /* Add a LAG member */ if (op == SET_COMMAND) { - string linkup_status; + string status; for (auto i : kfvFieldsValues(t)) { - if (fvField(i) == "linkup") - linkup_status = fvValue(i); + if (fvField(i) == "status") + status = fvValue(i); } - /* Add LAG member */ - if (linkup_status == "up") + /* Sync an enabled member */ + if (status == "enabled") { /* Duplicate entry */ if (lag.m_members.find(port_alias) != lag.m_members.end()) @@ -600,15 +601,11 @@ void PortsOrch::doLagTask(Consumer &consumer) else it++; } - /* Remove LAG member */ - else /* linkup_status == "down" */ + /* Sync an disabled member */ + else /* status == "disabled" */ { - assert(lag.m_members.find(port_alias) != lag.m_members.end()); - - /* Cannot locate LAG or LAG member - * This happens at the time when teamd starts. The linkup - * is set to down in the beginning. - */ + /* "status" is "disabled" at start when m_lag_id and + * m_lag_member_id are absent */ if (!port.m_lag_id || !port.m_lag_member_id) { it = consumer.m_toSync.erase(it); @@ -620,10 +617,11 @@ void PortsOrch::doLagTask(Consumer &consumer) else it++; } - } + /* Remove a LAG member */ else if (op == DEL_COMMAND) { + /* Assert the LAG member exists */ assert(lag.m_members.find(port_alias) != lag.m_members.end()); /* Assert the port belongs to a LAG */ diff --git a/teamsyncd/teamsync.cpp b/teamsyncd/teamsync.cpp index 85a61f76aa8d..fc44ae4b23ad 100644 --- a/teamsyncd/teamsync.cpp +++ b/teamsyncd/teamsync.cpp @@ -84,7 +84,7 @@ void TeamSync::removeLag(const string &lagName) const struct team_change_handler TeamSync::TeamPortSync::gPortChangeHandler = { .func = TeamSync::TeamPortSync::teamdHandler, - .type_mask = TEAM_PORT_CHANGE + .type_mask = TEAM_PORT_CHANGE | TEAM_OPTION_CHANGE }; TeamSync::TeamPortSync::TeamPortSync(const string &lagName, int ifindex, @@ -119,7 +119,8 @@ TeamSync::TeamPortSync::TeamPortSync(const string &lagName, int ifindex, "Unable to register port change event"); } - onPortChange(true); + /* Sync LAG at first */ + onChange(); } TeamSync::TeamPortSync::~TeamPortSync() @@ -131,42 +132,60 @@ TeamSync::TeamPortSync::~TeamPortSync() } } -int TeamSync::TeamPortSync::onPortChange(bool isInit) +int TeamSync::TeamPortSync::onChange() { struct team_port *port; + map tmp_lag_members; + + /* Check each port */ team_for_each_port(port, m_team) { - if (isInit || team_is_port_changed(port)) + uint32_t ifindex; + char ifname[MAX_IFNAME + 1] = {0}; + bool enabled; + + ifindex = team_get_port_ifindex(port); + team_ifindex2ifname(m_team, ifindex, ifname, MAX_IFNAME); + + /* Skip the member that is removed from the LAG */ + if (team_is_port_removed(port)) + continue; + + team_get_port_enabled(m_team, ifindex, &enabled); + tmp_lag_members[string(ifname)] = enabled; + } + + /* Compare old and new LAG members and set/del accordingly */ + for (auto it : tmp_lag_members) + { + if (m_lagMembers.find(it.first) == m_lagMembers.end() || it.second != m_lagMembers[it.first]) { - string key = m_lagName; - key += ":"; - uint32_t ifindex = team_get_port_ifindex(port); - char ifname[MAX_IFNAME + 1] = {0}; - key += team_ifindex2ifname(m_team, ifindex, ifname, MAX_IFNAME); - - if (team_is_port_removed(port)) - { - m_lagTable->del(key); - } else - { - std::vector fvVector; - FieldValueTuple l("linkup", team_is_port_link_up(port) ? "up" : "down"); - FieldValueTuple s("speed", to_string(team_get_port_speed(port)) + "Mbit"); - FieldValueTuple d("duplex", team_get_port_duplex(port) ? "full" : "half"); - fvVector.push_back(l); - fvVector.push_back(s); - fvVector.push_back(d); - m_lagTable->set(key, fvVector); - } + string key = m_lagName + ":" + it.first; + vector v; + FieldValueTuple l("status", it.second ? "enabled" : "disabled"); + v.push_back(l); + m_lagTable->set(key, v); } } + + for (auto it : m_lagMembers) + { + if (tmp_lag_members.find(it.first) == tmp_lag_members.end()) + { + string key = m_lagName + ":" + it.first; + m_lagTable->del(key); + } + } + + /* Replace the old LAG members with the new ones */ + m_lagMembers = tmp_lag_members; return 0; } int TeamSync::TeamPortSync::teamdHandler(struct team_handle *team, void *arg, team_change_type_mask_t type_mask) { - return ((TeamSync::TeamPortSync *)arg)->onPortChange(false); + return ((TeamSync::TeamPortSync *)arg)->onChange(); } void TeamSync::TeamPortSync::addFd(fd_set *fd) diff --git a/teamsyncd/teamsync.h b/teamsyncd/teamsync.h index bc353e1c7bf9..8fb61fd1cbcc 100644 --- a/teamsyncd/teamsync.h +++ b/teamsyncd/teamsync.h @@ -38,7 +38,7 @@ class TeamSync : public NetMsg virtual void readMe(); protected: - int onPortChange(bool isInit); + int onChange(); static int teamdHandler(struct team_handle *th, void *arg, team_change_type_mask_t type_mask); static const struct team_change_handler gPortChangeHandler; @@ -47,6 +47,7 @@ class TeamSync : public NetMsg struct team_handle *m_team; std::string m_lagName; int m_ifindex; + std::map m_lagMembers; /* map[ifname] = status (enabled|disabled) */ }; protected: