Skip to content
5 changes: 5 additions & 0 deletions orchagent/intfsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,11 @@ void IntfsOrch::voqSyncAddIntf(string &alias)
return;
}

if(alias.empty())
{
SWSS_LOG_ERROR("System Port/LAG alias is empty for %s!", port.m_alias.c_str());
return;
}

string oper_status = port.m_oper_status == SAI_PORT_OPER_STATUS_UP ? "up" : "down";

Expand Down
80 changes: 78 additions & 2 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
/* Initialize port and vlan table */
m_portTable = unique_ptr<Table>(new Table(db, APP_PORT_TABLE_NAME));
m_sendToIngressPortTable = unique_ptr<Table>(new Table(db, APP_SEND_TO_INGRESS_PORT_TABLE_NAME));
m_systemPortTable = unique_ptr<Table>(new Table(db, APP_SYSTEM_PORT_TABLE_NAME));

/* Initialize gearbox */
m_gearboxTable = unique_ptr<Table>(new Table(db, "_GEARBOX_TABLE"));
Expand Down Expand Up @@ -3973,6 +3974,7 @@ void PortsOrch::registerPort(Port &p)

/* Create associated Gearbox lane mapping */
initGearboxPort(p);
updateSystemPort(p);

/* Add port to port list */
m_portList[alias] = p;
Expand Down Expand Up @@ -10017,7 +10019,9 @@ bool PortsOrch::getSystemPorts()
attr.value.sysportconfig.attached_core_index,
attr.value.sysportconfig.attached_core_port_index);

m_systemPortOidMap[sp_key] = system_port_list[i];
systemPortMapInfo system_port_info;
system_port_info.system_port_id = system_port_list[i];
m_systemPortOidMap[sp_key] = system_port_info;
}
}

Expand Down Expand Up @@ -10103,7 +10107,8 @@ bool PortsOrch::addSystemPorts()
sai_status_t status;

//Retrive system port config info and enable
system_port_oid = m_systemPortOidMap[sp_key];
system_port_oid = m_systemPortOidMap[sp_key].system_port_id;


attr.id = SAI_SYSTEM_PORT_ATTR_TYPE;
attrs.push_back(attr);
Expand Down Expand Up @@ -10166,6 +10171,10 @@ bool PortsOrch::addSystemPorts()
port.m_system_port_info.speed = attrs[1].value.sysportconfig.speed;
port.m_system_port_info.num_voq = attrs[1].value.sysportconfig.num_voq;

//Update the system Port Info to the m_systemPortOidMap to be used later when the Port Speed is changed dynamically
m_systemPortOidMap[sp_key].system_port_info = port.m_system_port_info;
m_systemPortOidMap[sp_key].info_valid = true;

initializeVoqs( port );
setPort(port.m_alias, port);
/* Add system port name map to counter table */
Expand Down Expand Up @@ -10194,6 +10203,73 @@ bool PortsOrch::addSystemPorts()
return true;
}

void PortsOrch::updateSystemPort(Port &port)
{
if (!m_initDone)
{
//addSystemPorts will update the system port
return;
}

if ((gMySwitchType == "voq") && (port.m_type == Port::PHY))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may need to be addressed as per this PR - #3847

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may need to be addressed as per this PR - #3847

@prsunny , The PR #3847 added the isChassisDbInUse check only if it needs to access the CHASSIS_DB. But the code changes in this PR doesn't read/write from CHASSIS_DB and it just reads from APP_DB and update the Port structure

{
auto system_port_alias = gMyHostName + "|" + gMyAsicName + "|" + port.m_alias;
vector<FieldValueTuple> spFv;

m_systemPortTable->get(system_port_alias, spFv);

//Retrieve system port configurations from APP DB
int32_t switch_id = -1;
int32_t core_index = -1;
int32_t core_port_index = -1;

for ( auto &fv : spFv )
{
if(fv.first == "switch_id")
{
switch_id = stoi(fv.second);
continue;
}
if(fv.first == "core_index")
{
core_index = stoi(fv.second);
continue;
}
if(fv.first == "core_port_index")
{
core_port_index = stoi(fv.second);
continue;
}
if(switch_id < 0 || core_index < 0 || core_port_index < 0)
{
continue;
}
tuple<int, int, int> sp_key(switch_id, core_index, core_port_index);

if(m_systemPortOidMap.find(sp_key) != m_systemPortOidMap.end())
{
auto system_port = m_systemPortOidMap[sp_key];
// Check if the system_port_info is already populated in m_systemPortOidMap.
if(system_port.info_valid)
{
port.m_system_port_oid = system_port.system_port_id;
port.m_system_port_info = system_port.system_port_info;
port.m_system_port_info.local_port_oid = port.m_port_id;
//initializeVoqs(port);
SWSS_LOG_NOTICE("Updated system port for %s with system_port_alias:%s switch_id:%d, core_index:%d, core_port_index:%d",
port.m_alias.c_str(), system_port.system_port_info.alias.c_str(), system_port.system_port_info.switch_id,
system_port.system_port_info.core_index, system_port.system_port_info.core_port_index);
}
}
}
if(port.m_system_port_info.alias.empty())
{
SWSS_LOG_ERROR("SYSTEM PORT Information is not updated for %s", port.m_alias.c_str());
}
}
}


bool PortsOrch::getInbandPort(Port &port)
{
if (m_portList.find(m_inbandPortName) == m_portList.end())
Expand Down
11 changes: 10 additions & 1 deletion orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ struct queueInfo
sai_uint8_t index;
};

struct systemPortMapInfo
{
sai_object_id_t system_port_id;
SystemPortInfo system_port_info;
bool info_valid = false;
};

template<typename T>
struct PortCapability
{
Expand Down Expand Up @@ -264,6 +271,7 @@ class PortsOrch : public Orch, public Subject
unique_ptr<Table> m_counterLagTable;
unique_ptr<Table> m_portTable;
unique_ptr<Table> m_sendToIngressPortTable;
unique_ptr<Table> m_systemPortTable;
unique_ptr<Table> m_gearboxTable;
unique_ptr<CounterNameMapUpdater> m_queueCounterNameMapUpdater;
unique_ptr<Table> m_voqTable;
Expand Down Expand Up @@ -544,10 +552,11 @@ class PortsOrch : public Orch, public Subject
map<string, Port::Role> m_recircPortRole;

//map key is tuple of <attached_switch_id, core_index, core_port_index>
map<tuple<int, int, int>, sai_object_id_t> m_systemPortOidMap;
map<tuple<int, int, int>, systemPortMapInfo> m_systemPortOidMap;
sai_uint32_t m_systemPortCount;
bool getSystemPorts();
bool addSystemPorts();
void updateSystemPort(Port &port);
unique_ptr<Table> m_tableVoqSystemLagTable;
unique_ptr<Table> m_tableVoqSystemLagMemberTable;
void voqSyncAddLag(Port &lag);
Expand Down
128 changes: 72 additions & 56 deletions tests/test_virtual_chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,62 +915,6 @@ def test_chassis_system_lag_id_allocator_del_id(self, vct):

break

def test_chassis_add_remove_ports(self, vct):
"""Test removing and adding a port in a VOQ chassis.

Test validates that when a port is created the port is removed from the default vlan.
"""
dvss = vct.dvss
for name in dvss.keys():
dvs = dvss[name]
buffer_model.enable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd)

config_db = dvs.get_config_db()
app_db = dvs.get_app_db()
asic_db = dvs.get_asic_db()
metatbl = config_db.get_entry("DEVICE_METADATA", "localhost")
cfg_switch_type = metatbl.get("switch_type")

if cfg_switch_type == "voq":
num_ports = len(asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT"))
# Get the port info we'll flap
port = config_db.get_keys('PORT')[0]
port_info = config_db.get_entry("PORT", port)

# Remove port's other configs
pgs = config_db.get_keys('BUFFER_PG')
queues = config_db.get_keys('BUFFER_QUEUE')
for key in pgs:
if port in key:
config_db.delete_entry('BUFFER_PG', key)
app_db.wait_for_deleted_entry('BUFFER_PG_TABLE', key)

for key in queues:
if port in key:
config_db.delete_entry('BUFFER_QUEUE', key)
app_db.wait_for_deleted_entry('BUFFER_QUEUE_TABLE', key)

# Remove port
config_db.delete_entry('PORT', port)
app_db.wait_for_deleted_entry('PORT_TABLE', port)
num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT",
num_ports)
assert len(num) == num_ports

# Create port
config_db.update_entry("PORT", port, port_info)
app_db.wait_for_entry("PORT_TABLE", port)
num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT",
num_ports)
assert len(num) == num_ports

# Check that we see the logs for removing default vlan
_, logSeen = dvs.runcmd( [ "sh", "-c",
"awk STARTFILE/ENDFILE /var/log/syslog | grep 'removeDefaultVlanMembers: Remove 32 VLAN members from default VLAN' | wc -l"] )
assert logSeen.strip() == "1"

buffer_model.disable_dynamic_buffer(dvs)

def test_voq_egress_queue_counter(self, vct):
if vct is None:
return
Expand Down Expand Up @@ -1038,6 +982,78 @@ def test_chassis_wred_profile_on_system_ports(self, vct):
# Total number of logs = (No of system ports * No of lossless priorities) - No of lossless priorities for CPU ports
assert logSeen.strip() == str(len(system_ports)*2 - 2)

def test_chassis_add_remove_ports(self, vct):
"""Test removing and adding a port in a VOQ chassis.

Test validates that when a port is created the port is removed from the default vlan.
"""
dvss = vct.dvss
for name in dvss.keys():
dvs = dvss[name]
buffer_model.enable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd)

config_db = dvs.get_config_db()
app_db = dvs.get_app_db()
asic_db = dvs.get_asic_db()
metatbl = config_db.get_entry("DEVICE_METADATA", "localhost")
cfg_switch_type = metatbl.get("switch_type")
cfg_hostname = metatbl.get("hostname")
cfg_asic_name = metatbl.get("asic_name")

if cfg_switch_type == "voq":
num_ports = len(asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT"))
# Get the port info we'll flap
port = config_db.get_keys('PORT')[0]
port_info = config_db.get_entry("PORT", port)
system_port = cfg_hostname+"|"+cfg_asic_name+"|"+port

# Remove port's other configs
pgs = config_db.get_keys('BUFFER_PG')
buf_queues = config_db.get_keys('BUFFER_QUEUE')
queues = config_db.get_keys('QUEUE')
for key in pgs:
if port in key:
config_db.delete_entry('BUFFER_PG', key)
app_db.wait_for_deleted_entry('BUFFER_PG_TABLE', key)

for key in buf_queues:
if port in key:
config_db.delete_entry('BUFFER_QUEUE', key)
app_db.wait_for_deleted_entry('BUFFER_QUEUE_TABLE', key)

queue_info = {}
for key in queues:
if system_port in key:
queue_info[key] = config_db.get_entry("QUEUE", key)
config_db.delete_entry('QUEUE', key)
config_db.wait_for_deleted_entry('QUEUE_TABLE', key)

# Remove port
config_db.delete_entry('PORT', port)
app_db.wait_for_deleted_entry('PORT_TABLE', port)
num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT",
num_ports)
assert len(num) == num_ports

# Create port
config_db.update_entry("PORT", port, port_info)
app_db.wait_for_entry("PORT_TABLE", port)
num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT",
num_ports)
assert len(num) == num_ports

if len(queue_info):
for key, value in queue_info.items():
config_db.update_entry("QUEUE", key, value)
config_db.wait_for_entry("QUEUE", key)

# Check that we see the logs for removing default vlan
_, logSeen = dvs.runcmd( [ "sh", "-c",
"awk STARTFILE/ENDFILE /var/log/syslog | grep 'removeDefaultVlanMembers: Remove 32 VLAN members from default VLAN' | wc -l"] )
assert logSeen.strip() == "1"

buffer_model.disable_dynamic_buffer(dvs)

def test_chassis_system_intf_status(self, vct):
dvs = self.get_sup_dvs(vct)
chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock)
Expand Down
Loading