Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f0b2cec
changes needed to support VOQ FS
lakshmi-nexthop Aug 27, 2025
9925e34
connect to chassis db if present
lakshmi-nexthop Aug 27, 2025
a878c08
UT fix
lakshmi-nexthop Aug 29, 2025
756c48c
format
lakshmi-nexthop Oct 7, 2025
77b17bf
formatting
lakshmi-nexthop Oct 7, 2025
a63b4d9
format
lakshmi-nexthop Oct 7, 2025
49d7b93
format
lakshmi-nexthop Oct 7, 2025
f1a54fa
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Oct 7, 2025
7e36333
conflict
lakshmi-nexthop Oct 7, 2025
6140dd1
UT for fixed system voq
lakshmi-nexthop Oct 15, 2025
a5a7d9b
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Oct 22, 2025
4028a48
UT invocation
lakshmi-nexthop Oct 22, 2025
49f2df5
removed call to 2nd run-tests.sh
lakshmi-nexthop Oct 23, 2025
a9b094d
removed docker-sonic-vs changes also
lakshmi-nexthop Oct 23, 2025
5561705
Added UT back
lakshmi-nexthop Oct 23, 2025
7a6d0ae
change name
lakshmi-nexthop Oct 24, 2025
0780b1c
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Oct 24, 2025
504be65
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Oct 25, 2025
212f021
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Oct 28, 2025
340f91a
refactor to reduce checks for single asic
lakshmi-nexthop Nov 13, 2025
b90964a
Merge branch 'single_voq_swss' of github.com:lakshmi-nexthop/sonic-sw…
lakshmi-nexthop Nov 13, 2025
e563a9b
removed extra lines
lakshmi-nexthop Nov 13, 2025
74427f6
add line
lakshmi-nexthop Nov 13, 2025
b220bb4
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Nov 13, 2025
566e45b
removed more checks
lakshmi-nexthop Nov 13, 2025
f2e9985
removed additional check for voq
lakshmi-nexthop Nov 13, 2025
eae99a5
format
lakshmi-nexthop Nov 14, 2025
5e89254
format
lakshmi-nexthop Nov 14, 2025
36fd1c2
Merge branch 'master' into single_voq_swss
lakshmi-nexthop Nov 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .azure-pipelines/docker-sonic-vs/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,15 @@ else
qos_cmd="-j /tmp/qos.json"
fi

if [ -f /usr/share/sonic/single_asic_voq_fs/default_config.json ]; then
sonic-cfggen -j /usr/share/sonic/single_asic_voq_fs/default_config.json --print-data > /tmp/voq.json
voq_cmd="-j /tmp/voq.json"
fi

sonic-cfggen -p /usr/share/sonic/device/$PLATFORM/$PLATFORM_CONF -k $HWSKU --print-data > /tmp/ports.json
# change admin_status from up to down; Test cases dependent
sed -i "s/up/down/g" /tmp/ports.json
sonic-cfggen -j /etc/sonic/init_cfg.json $buffers_cmd $qos_cmd -j /tmp/ports.json --print-data > /etc/sonic/config_db.json
sonic-cfggen -j /etc/sonic/init_cfg.json $buffers_cmd $qos_cmd $voq_cmd -j /tmp/ports.json --print-data > /etc/sonic/config_db.json
fi

sonic-cfggen -t /usr/share/sonic/templates/copp_cfg.j2 > /etc/sonic/copp_cfg.json
Expand Down
2 changes: 2 additions & 0 deletions .azure-pipelines/test-docker-sonic-vs-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ jobs:
retry=3
IMAGE_NAME=docker-sonic-vs:$(Build.DefinitionName).$(Build.BuildNumber).asan-${{ parameters.asan }}
echo $all_tests | xargs -n 1 | xargs -P 8 -I TEST_MODULE sudo DEFAULT_CONTAINER_REGISTRY=publicmirror.azurecr.io/ ./run-tests.sh "$IMAGE_NAME" "$params" "TEST_MODULE" 3
single_asic_voq_tests="test_portchannel.py test_neighbor.py test_route.py"
echo $single_asic_voq_tests | xargs -n 1 | xargs -P 3 -I TEST_MODULE sudo ./run-tests.sh "$IMAGE_NAME" "--force-recreate-dvs --switch-mode=single_asic_voq_fs" "TEST_MODULE" 3

rm -rf $(Build.ArtifactStagingDirectory)/download
displayName: "Run vs tests"
Expand Down
7 changes: 4 additions & 3 deletions orchagent/intfsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extern NeighOrch *gNeighOrch;
extern string gMySwitchType;
extern int32_t gVoqMySwitchId;
extern bool gTraditionalFlexCounter;
extern bool isChassisDbInUse();

const int intfsorch_pri = 35;

Expand Down Expand Up @@ -98,7 +99,7 @@ IntfsOrch::IntfsOrch(DBConnector *db, string tableName, VRFOrch *vrf_orch, DBCon
RIF_PLUGIN_FIELD,
rifRateSha);

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
//Add subscriber to process VOQ system interface
tableName = CHASSIS_APP_SYSTEM_INTERFACE_TABLE_NAME;
Expand Down Expand Up @@ -1310,7 +1311,7 @@ bool IntfsOrch::addRouterIntfs(sai_object_id_t vrf_id, Port &port, string loopba

SWSS_LOG_NOTICE("Create router interface %s MTU %u", port.m_alias.c_str(), port.m_mtu);

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
// Sync the interface of local port/LAG to the SYSTEM_INTERFACE table of CHASSIS_APP_DB
voqSyncAddIntf(port.m_alias);
Expand Down Expand Up @@ -1363,7 +1364,7 @@ bool IntfsOrch::removeRouterIntfs(Port &port)

SWSS_LOG_NOTICE("Remove router interface for port %s", port.m_alias.c_str());

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
// Sync the removal of interface of local port/LAG to the SYSTEM_INTERFACE table of CHASSIS_APP_DB
voqSyncDelIntf(port.m_alias);
Expand Down
43 changes: 40 additions & 3 deletions orchagent/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ extern "C" {
#include <stdexcept>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <nlohmann/json.hpp>

#include <sys/time.h>
#include <sairedis.h>
Expand Down Expand Up @@ -77,6 +79,12 @@ string gMyHostName = "";
string gMyAsicName = "";
bool gTraditionalFlexCounter = false;
uint32_t create_switch_timeout = 0;
bool gMultiAsicVoq = false;

bool isChassisDbInUse()
{
return gMultiAsicVoq;
}

void usage()
{
Expand Down Expand Up @@ -208,6 +216,18 @@ void getCfgSwitchType(DBConnector *cfgDb, string &switch_type, string &switch_su

}

bool isChassisAppDbPresent()
{
std::ifstream file("/etc/sonic/database_config.json");
if (!file.is_open()) return false;

nlohmann::json db_config;
file >> db_config;

return db_config.contains("DATABASES") &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we handle this by any other field in Config_DB and not reading file? @arlakshm

Choose a reason for hiding this comment

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

At some point, there was an idea/suggestion to use a different flag in DEVICE_METADATA to indicate this mode. It's definitely a plausible solution, but a bit redundant and we have to worry about inconsistency between what that flag says and the presence/absence of this file. Both are valid approaches though and it will be good to see what @arlakshm suggests here

Copy link
Contributor

Choose a reason for hiding this comment

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

@tjchadaga : can you put final conclusion here ?

Copy link
Contributor

Choose a reason for hiding this comment

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

@prsunny, currently we do not have any config_db entry to identify this. We can keep the check for chassis_db.conf. We will revisit this once we have any config_db entry is added

db_config["DATABASES"].contains("CHASSIS_APP_DB");
}

bool getSystemPortConfigList(DBConnector *cfgDb, DBConnector *appDb, vector<sai_system_port_config_t> &sysportcfglist)
{
Table cfgDeviceMetaDataTable(cfgDb, CFG_DEVICE_METADATA_TABLE_NAME);
Expand Down Expand Up @@ -617,7 +637,19 @@ int main(int argc, char **argv)

//Connect to CHASSIS_APP_DB in redis-server in control/supervisor card as per
//connection info in database_config.json
chassis_app_db = make_shared<DBConnector>("CHASSIS_APP_DB", 0, true);
chassis_app_db = nullptr;
if (isChassisAppDbPresent())
{
gMultiAsicVoq = true;
try
{
chassis_app_db = make_shared<DBConnector>("CHASSIS_APP_DB", 0, true);
}
catch (const std::exception& e)
{
SWSS_LOG_NOTICE("CHASSIS_APP_DB not available, operating in standalone VOQ mode");
}
}
}
else if (gMySwitchType == "fabric")
{
Expand Down Expand Up @@ -867,6 +899,11 @@ int main(int argc, char **argv)
}

shared_ptr<OrchDaemon> orchDaemon;
DBConnector *chassis_db = nullptr;
if (chassis_app_db != nullptr)
{
chassis_db = chassis_app_db.get();
}

/*
* Declare shared pointers for dpu specific databases.
Expand All @@ -884,7 +921,7 @@ int main(int argc, char **argv)

else if (gMySwitchType != "fabric")
{
orchDaemon = make_shared<OrchDaemon>(&appl_db, &config_db, &state_db, chassis_app_db.get(), zmq_server.get());
orchDaemon = make_shared<OrchDaemon>(&appl_db, &config_db, &state_db, chassis_db, zmq_server.get());
if (gMySwitchType == "voq")
{
orchDaemon->setFabricEnabled(true);
Expand All @@ -894,7 +931,7 @@ int main(int argc, char **argv)
}
else
{
orchDaemon = make_shared<FabricOrchDaemon>(&appl_db, &config_db, &state_db, chassis_app_db.get(), zmq_server.get());
orchDaemon = make_shared<FabricOrchDaemon>(&appl_db, &config_db, &state_db, chassis_db, zmq_server.get());
}

if (gRingMode) {
Expand Down
8 changes: 5 additions & 3 deletions orchagent/neighorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ extern BfdOrch *gBfdOrch;
extern size_t gMaxBulkSize;
extern string gMyHostName;

extern bool isChassisDbInUse();

const int neighorch_pri = 30;

NeighOrch::NeighOrch(DBConnector *appDb, string tableName, IntfsOrch *intfsOrch, FdbOrch *fdbOrch, PortsOrch *portsOrch, DBConnector *chassisAppDb) :
Expand All @@ -46,7 +48,7 @@ NeighOrch::NeighOrch(DBConnector *appDb, string tableName, IntfsOrch *intfsOrch,
gBfdOrch->attach(this);
}

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
//Add subscriber to process VOQ system neigh
tableName = CHASSIS_APP_SYSTEM_NEIGH_TABLE_NAME;
Expand Down Expand Up @@ -1230,7 +1232,7 @@ bool NeighOrch::addNeighbor(NeighborContext& ctx)
NeighborUpdate update = { neighborEntry, macAddress, true };
notify(SUBJECT_TYPE_NEIGH_CHANGE, static_cast<void *>(&update));

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
//Sync the neighbor to add to the CHASSIS_APP_DB
voqSyncAddNeigh(alias, ip_address, macAddress, neighbor_entry);
Expand Down Expand Up @@ -1379,7 +1381,7 @@ bool NeighOrch::removeNeighbor(NeighborContext& ctx, bool disable)
NeighborUpdate update = { neighborEntry, MacAddress(), false };
notify(SUBJECT_TYPE_NEIGH_CHANGE, static_cast<void *>(&update));

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
//Sync the neighbor to delete from the CHASSIS_APP_DB
voqSyncDelNeigh(alias, ip_address);
Expand Down
32 changes: 19 additions & 13 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ extern int32_t gVoqMySwitchId;
extern string gMyHostName;
extern string gMyAsicName;
extern event_handle_t g_events_handle;
extern bool isChassisDbInUse();
extern bool gMultiAsicVoq;

// defines ------------------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -989,7 +991,7 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
Orch::addExecutor(portHostTxReadyNotificatier);
}

if (gMySwitchType == "voq")
if (isChassisDbInUse())
{
string tableName;
//Add subscriber to process system LAG (System PortChannel) table
Expand Down Expand Up @@ -5985,7 +5987,7 @@ void PortsOrch::doLagMemberTask(Consumer &consumer)
}
}

if ((gMySwitchType == "voq") && (port.m_type != Port::SYSTEM))
if (isChassisDbInUse() && (port.m_type != Port::SYSTEM))
{
//Sync to SYSTEM_LAG_MEMBER_TABLE of CHASSIS_APP_DB
voqSyncAddLagMember(lag, port, status);
Expand Down Expand Up @@ -7584,13 +7586,16 @@ bool PortsOrch::addLag(string lag_alias, uint32_t spa_id, int32_t switch_id)
switch_id = gVoqMySwitchId;
system_lag_alias = gMyHostName + "|" + gMyAsicName + "|" + lag_alias;

// Allocate unique lag id
spa_id = m_lagIdAllocator->lagIdAdd(system_lag_alias, 0);

if ((int32_t)spa_id <= 0)
if (gMultiAsicVoq)
{
SWSS_LOG_ERROR("Failed to allocate unique LAG id for local lag %s rv:%d", lag_alias.c_str(), spa_id);
return false;
// Allocate unique lag id
spa_id = m_lagIdAllocator->lagIdAdd(system_lag_alias, 0);

if ((int32_t)spa_id <= 0)
{
SWSS_LOG_ERROR("Failed to allocate unique LAG id for local lag %s rv:%d", lag_alias.c_str(), spa_id);
return false;
}
}
}

Expand Down Expand Up @@ -7702,7 +7707,7 @@ bool PortsOrch::removeLag(Port lag)

m_counterLagTable->hdel("", lag.m_alias);

if (gMySwitchType == "voq")
if (isChassisDbInUse())
{
// Free the lag id, if this is local LAG

Expand Down Expand Up @@ -7815,7 +7820,7 @@ bool PortsOrch::addLagMember(Port &lag, Port &port, string member_status)
LagMemberUpdate update = { lag, port, true };
notify(SUBJECT_TYPE_LAG_MEMBER_CHANGE, static_cast<void *>(&update));

if (gMySwitchType == "voq")
if (isChassisDbInUse())
{
//Sync to SYSTEM_LAG_MEMBER_TABLE of CHASSIS_APP_DB
voqSyncAddLagMember(lag, port, member_status);
Expand Down Expand Up @@ -7863,7 +7868,7 @@ bool PortsOrch::removeLagMember(Port &lag, Port &port)
LagMemberUpdate update = { lag, port, false };
notify(SUBJECT_TYPE_LAG_MEMBER_CHANGE, static_cast<void *>(&update));

if (gMySwitchType == "voq")
if (isChassisDbInUse())
{
//Sync to SYSTEM_LAG_MEMBER_TABLE of CHASSIS_APP_DB
voqSyncDelLagMember(lag, port);
Expand Down Expand Up @@ -9100,7 +9105,7 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status)
}
}

if(gMySwitchType == "voq")
if(isChassisDbInUse())
{
if (gIntfsOrch->isLocalSystemPortIntf(port.m_alias))
{
Expand Down Expand Up @@ -10247,7 +10252,8 @@ void PortsOrch::voqSyncAddLag (Port &lag)

// Sync only local lag add to CHASSIS_APP_DB

if (switch_id != gVoqMySwitchId)
if (switch_id != gVoqMySwitchId ||
!gMultiAsicVoq)
{
return;
}
Expand Down
36 changes: 31 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
# Voq asics will have 16 fabric ports created (defined in Azure/sonic-buildimage#7629).
FABRIC_NUM_PORTS = 16

SINGLE_ASIC_VOQ_FS = "single_asic_voq_fs"

def ensure_system(cmd):
rc, output = subprocess.getstatusoutput(cmd)
if rc:
Expand Down Expand Up @@ -112,6 +114,12 @@ def pytest_addoption(parser):
default=False,
help="Collect the test coverage information")

parser.addoption("--switch-mode",
action="store",
default=None,
type=str,
help="Set switch mode information")


def random_string(size=4, chars=string.ascii_uppercase + string.digits):
return "".join(random.choice(chars) for x in range(size))
Expand Down Expand Up @@ -293,7 +301,8 @@ def __init__(
newctnname: str = None,
ctnmounts: Dict[str, str] = None,
buffer_model: str = None,
enable_coverage: bool = False
enable_coverage: bool = False,
switch_mode: str = None
):
self.basicd = ["redis-server", "rsyslogd"]
self.swssd = [
Expand All @@ -316,6 +325,7 @@ def __init__(
self.vct = vct
self.ctn = None
self.enable_coverage = enable_coverage
self.switch_mode = switch_mode

self.cleanup = not keeptb

Expand Down Expand Up @@ -577,7 +587,10 @@ def check_swss_ready(self, timeout: int = 300) -> None:
self.get_config_db()
metadata = self.config_db.get_entry('DEVICE_METADATA|localhost', '')
if metadata.get('switch_type', 'npu') in ['voq', 'fabric']:
num_ports = NUM_PORTS + FABRIC_NUM_PORTS
if self.switch_mode and self.switch_mode == SINGLE_ASIC_VOQ_FS:
num_ports = NUM_PORTS
else:
num_ports = NUM_PORTS + FABRIC_NUM_PORTS

# Verify that all ports have been initialized and configured
app_db = self.get_app_db()
Expand All @@ -597,8 +610,9 @@ def _polling_function():

# Verify that fabric ports are monitored in STATE_DB
if metadata.get('switch_type', 'npu') in ['voq', 'fabric']:
self.get_state_db()
self.state_db.wait_for_n_keys("FABRIC_PORT_TABLE", FABRIC_NUM_PORTS)
if not self.switch_mode or (self.switch_mode and self.switch_mode != SINGLE_ASIC_VOQ_FS):
self.get_state_db()
self.state_db.wait_for_n_keys("FABRIC_PORT_TABLE", FABRIC_NUM_PORTS)

def net_cleanup(self) -> None:
"""Clean up network, remove extra links."""
Expand Down Expand Up @@ -1669,6 +1683,11 @@ def create_vct_ctn(self, ctndir):
vol = {}
vol[chassis_config_dir] = {"bind": "/usr/share/sonic/virtual_chassis", "mode": "ro"}

# Mount database_config.json when connect_to_chassis_db is set to 1
if defcfg.get("connect_to_chassis_db") == 1:
database_config_file = cwd + "/virtual_chassis/database_config.json"
vol[database_config_file] = {"bind": "/etc/sonic/database_config.json", "mode": "ro"}

# pass self.ns into the vs to be use for vs restarts by swss conftest.
# connection to chassbr is setup by chassis_connect.py within the vs
data = {}
Expand Down Expand Up @@ -1859,6 +1878,7 @@ def manage_dvs(request) -> str:
force_recreate = request.config.getoption("--force-recreate-dvs")
graceful_stop = request.config.getoption("--graceful-stop")
enable_coverage = request.config.getoption("--enable-coverage")
switch_mode = request.config.getoption("--switch-mode")

dvs = None
curr_dvs_env = [] # lgtm[py/unused-local-variable]
Expand Down Expand Up @@ -1890,7 +1910,13 @@ def update_dvs(log_path, new_dvs_env=[]):
dvs.get_logs()
dvs.destroy()

dvs = DockerVirtualSwitch(name, imgname, keeptb, new_dvs_env, log_path, max_cpu, forcedvs, buffer_model = buffer_model, enable_coverage=enable_coverage)
vol = {}
if switch_mode and switch_mode == SINGLE_ASIC_VOQ_FS:
cwd = os.getcwd()
voq_configs = cwd + "/single_asic_voq_fs"
vol[voq_configs] = {"bind": "/usr/share/sonic/single_asic_voq_fs", "mode": "ro"}

dvs = DockerVirtualSwitch(name, imgname, keeptb, new_dvs_env, log_path, max_cpu, forcedvs, buffer_model = buffer_model, enable_coverage=enable_coverage, ctnmounts=vol, switch_mode=switch_mode)

curr_dvs_env = new_dvs_env

Expand Down
Loading
Loading