Skip to content

Commit 4f1d726

Browse files
[portsorch] fix errors when moving port from one lag to another. (sonic-net#1797)
In scenario that is executed in sonic-mgmt in test_po_update.py a portchannel member is deleted from one portchannel and added to another portchannel. It is possible that requests from teamsynd will arrive in different order This reordering happens because teamsyncd has single event handler/selectable TeamSync::TeamPortSync::onChange() per team device so when two of them are ready it is swss::Select implementation detail in which order they are going to be returned. This is a fundamental issue of Producer/ConsumerStateTable, thus orchagent must be aware of this and treat it as normal situation and figure out the right order and not crash or print an errors. - What I did Check if port is already a lag member beforehand. Added an UT to cover this scenario, this UT verifies that SAI API is not called in this case. Refactored portsorch_ut.cpp by moving out Orchs creation/deletion into SetUp()/TearDown() - Why I did it To fix errors in log. - How I verified it Ran test_po_update.py test. Signed-off-by: Stepan Blyschak [email protected]
1 parent ae44701 commit 4f1d726

File tree

2 files changed

+176
-113
lines changed

2 files changed

+176
-113
lines changed

orchagent/portsorch.cpp

+35-16
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,12 @@ static char* hostif_vlan_tag[] = {
266266
[SAI_HOSTIF_VLAN_TAG_KEEP] = "SAI_HOSTIF_VLAN_TAG_KEEP",
267267
[SAI_HOSTIF_VLAN_TAG_ORIGINAL] = "SAI_HOSTIF_VLAN_TAG_ORIGINAL"
268268
};
269+
270+
static bool isValidPortTypeForLagMember(const Port& port)
271+
{
272+
return (port.m_type == Port::Type::PHY || port.m_type == Port::Type::SYSTEM);
273+
}
274+
269275
/*
270276
* Initialize PortsOrch
271277
* 0) If Gearbox is enabled, then initialize the external PHYs as defined in
@@ -1758,7 +1764,7 @@ void PortsOrch::getPortSupportedSpeeds(const std::string& alias, sai_object_id_t
17581764
}
17591765

17601766
// if our guess was wrong, retry with the correct value
1761-
speeds.resize(attr.value.u32list.count);
1767+
speeds.resize(attr.value.u32list.count);
17621768
}
17631769

17641770
if (status == SAI_STATUS_SUCCESS)
@@ -2243,7 +2249,7 @@ sai_status_t PortsOrch::removePort(sai_object_id_t port_id)
22432249

22442250
Port port;
22452251

2246-
/*
2252+
/*
22472253
* Make sure to bring down admin state.
22482254
* SET would have replaced with DEL
22492255
*/
@@ -2812,7 +2818,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
28122818
it = consumer.m_toSync.erase(it);
28132819
continue;
28142820
}
2815-
2821+
28162822
an = autoneg_mode_map[an_str];
28172823
if (an != p.m_autoneg)
28182824
{
@@ -2878,7 +2884,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
28782884
it++;
28792885
continue;
28802886
}
2881-
2887+
28822888
SWSS_LOG_NOTICE("Set port %s speed from %u to %u", alias.c_str(), p.m_speed, speed);
28832889
p.m_speed = speed;
28842890
m_portList[alias] = p;
@@ -2919,7 +2925,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
29192925
auto ori_adv_speeds = swss::join(',', p.m_adv_speeds.begin(), p.m_adv_speeds.end());
29202926
if (!setPortAdvSpeeds(p.m_port_id, adv_speeds))
29212927
{
2922-
2928+
29232929
SWSS_LOG_ERROR("Failed to set port %s advertised speed from %s to %s", alias.c_str(),
29242930
ori_adv_speeds.c_str(),
29252931
adv_speeds_str.c_str());
@@ -3713,6 +3719,15 @@ void PortsOrch::doLagMemberTask(Consumer &consumer)
37133719
continue;
37143720
}
37153721

3722+
/* Fail if a port type is not a valid type for being a LAG member port.
3723+
* Erase invalid entry, no need to retry in this case. */
3724+
if (!isValidPortTypeForLagMember(port))
3725+
{
3726+
SWSS_LOG_ERROR("LAG member port has to be of type PHY or SYSTEM");
3727+
it = consumer.m_toSync.erase(it);
3728+
continue;
3729+
}
3730+
37163731
if (table_name == CHASSIS_APP_LAG_MEMBER_TABLE_NAME)
37173732
{
37183733
int32_t lag_switch_id = lag.m_system_lag_info.switch_id;
@@ -3746,8 +3761,12 @@ void PortsOrch::doLagMemberTask(Consumer &consumer)
37463761

37473762
if (lag.m_members.find(port_alias) == lag.m_members.end())
37483763
{
3749-
/* Assert the port doesn't belong to any LAG already */
3750-
assert(!port.m_lag_id && !port.m_lag_member_id);
3764+
if (port.m_lag_member_id != SAI_NULL_OBJECT_ID)
3765+
{
3766+
SWSS_LOG_INFO("Port %s is already a LAG member", port.m_alias.c_str());
3767+
it++;
3768+
continue;
3769+
}
37513770

37523771
if (!addLagMember(lag, port, (status == "enabled")))
37533772
{
@@ -5567,7 +5586,7 @@ void PortsOrch::getPortSerdesVal(const std::string& val_str,
55675586
}
55685587
}
55695588

5570-
bool PortsOrch::getPortAdvSpeedsVal(const std::string &val_str,
5589+
bool PortsOrch::getPortAdvSpeedsVal(const std::string &val_str,
55715590
std::vector<uint32_t> &speed_values)
55725591
{
55735592
SWSS_LOG_ENTER();
@@ -5581,7 +5600,7 @@ bool PortsOrch::getPortAdvSpeedsVal(const std::string &val_str,
55815600
std::string speed_str;
55825601
std::istringstream iss(val_str);
55835602

5584-
try
5603+
try
55855604
{
55865605
while (std::getline(iss, speed_str, ','))
55875606
{
@@ -5598,31 +5617,31 @@ bool PortsOrch::getPortAdvSpeedsVal(const std::string &val_str,
55985617
return true;
55995618
}
56005619

5601-
bool PortsOrch::getPortInterfaceTypeVal(const std::string &s,
5620+
bool PortsOrch::getPortInterfaceTypeVal(const std::string &s,
56025621
sai_port_interface_type_t &interface_type)
56035622
{
56045623
SWSS_LOG_ENTER();
56055624

56065625
auto iter = interface_type_map_for_an.find(s);
5607-
if (iter != interface_type_map_for_an.end())
5626+
if (iter != interface_type_map_for_an.end())
56085627
{
56095628
interface_type = interface_type_map_for_an[s];
56105629
return true;
56115630
}
5612-
else
5631+
else
56135632
{
56145633
const std::string &validInterfaceTypes = getValidInterfaceTypes();
5615-
SWSS_LOG_ERROR("Failed to parse interface_type value %s, valid interface type includes: %s",
5634+
SWSS_LOG_ERROR("Failed to parse interface_type value %s, valid interface type includes: %s",
56165635
s.c_str(), validInterfaceTypes.c_str());
56175636
return false;
56185637
}
56195638
}
56205639

5621-
bool PortsOrch::getPortAdvInterfaceTypesVal(const std::string &val_str,
5640+
bool PortsOrch::getPortAdvInterfaceTypesVal(const std::string &val_str,
56225641
std::vector<uint32_t> &type_values)
56235642
{
56245643
SWSS_LOG_ENTER();
5625-
if (val_str == "all")
5644+
if (val_str == "all")
56265645
{
56275646
return true;
56285647
}
@@ -5637,7 +5656,7 @@ bool PortsOrch::getPortAdvInterfaceTypesVal(const std::string &val_str,
56375656
valid = getPortInterfaceTypeVal(type_str, interface_type);
56385657
if (!valid) {
56395658
const std::string &validInterfaceTypes = getValidInterfaceTypes();
5640-
SWSS_LOG_ERROR("Failed to parse adv_interface_types value %s, valid interface type includes: %s",
5659+
SWSS_LOG_ERROR("Failed to parse adv_interface_types value %s, valid interface type includes: %s",
56415660
val_str.c_str(), validInterfaceTypes.c_str());
56425661
return false;
56435662
}

0 commit comments

Comments
 (0)