syncd/tests.cpp (758 lines of code) (raw):
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
extern "C" {
#include <sai.h>
}
#include "lib/Sai.h"
#include "Syncd.h"
#include "MetadataLogger.h"
#include "sairedis.h"
#include "sairediscommon.h"
#include "TimerWatchdog.h"
#include "meta/sai_serialize.h"
#include "meta/OidRefCounter.h"
#include "meta/SaiAttrWrapper.h"
#include "meta/SaiObjectCollection.h"
#include "meta/RedisSelectableChannel.h"
#include "swss/logger.h"
#include "swss/dbconnector.h"
#include "swss/schema.h"
#include "swss/redisreply.h"
#include "swss/consumertable.h"
#include "swss/select.h"
#include <map>
#include <unordered_map>
#include <vector>
#include <thread>
#include <tuple>
using namespace syncd;
//static bool g_syncMode;
#define ASSERT_SUCCESS(format,...) \
if ((status)!=SAI_STATUS_SUCCESS) \
SWSS_LOG_THROW(format ": %s", ##__VA_ARGS__, sai_serialize_status(status).c_str());
#define SAI_FAILURE_DUMP_SCRIPT "/usr/bin/sai_failure_dump.sh"
#define CHECK_STATUS(x) \
if (status != SAI_STATUS_SUCCESS) { exit(1); }
using namespace saimeta;
std::string mockCallArg;
namespace swss {
int exec(const std::string &cmd, std::string &stdout)
{
SWSS_LOG_ENTER();
mockCallArg=cmd;
return 0;
}
}
static std::shared_ptr<swss::DBConnector> g_db1;
static std::shared_ptr<Syncd> g_syncd_obj;
static sai_next_hop_group_api_t test_next_hop_group_api;
static std::vector<std::tuple<sai_object_id_t, sai_object_id_t, std::vector<sai_attribute_t>>> created_next_hop_group_member;
sai_status_t test_create_next_hop_group_member(
_Out_ sai_object_id_t *next_hop_group_member_id,
_In_ sai_object_id_t switch_id,
_In_ uint32_t attr_count,
_In_ const sai_attribute_t *attr_list)
{
SWSS_LOG_ENTER();
created_next_hop_group_member.emplace_back();
auto& back = created_next_hop_group_member.back();
std::get<0>(back) = *next_hop_group_member_id;
std::get<1>(back) = switch_id;
auto& attrs = std::get<2>(back);
attrs.insert(attrs.end(), attr_list, attr_list + attr_count);
return 0;
}
void clearDB()
{
SWSS_LOG_ENTER();
g_db1 = std::make_shared<swss::DBConnector>("ASIC_DB", 0, true);
swss::RedisReply r(g_db1.get(), "FLUSHALL", REDIS_REPLY_STATUS);
r.checkStatusOK();
}
static const char* profile_get_value(
_In_ sai_switch_profile_id_t profile_id,
_In_ const char* variable)
{
SWSS_LOG_ENTER();
return NULL;
}
static int profile_get_next_value(
_In_ sai_switch_profile_id_t profile_id,
_Out_ const char** variable,
_Out_ const char** value)
{
SWSS_LOG_ENTER();
if (value == NULL)
{
SWSS_LOG_INFO("resetting profile map iterator");
return 0;
}
if (variable == NULL)
{
SWSS_LOG_WARN("variable is null");
return -1;
}
SWSS_LOG_INFO("iterator reached end");
return -1;
}
static sai_service_method_table_t test_services = {
profile_get_value,
profile_get_next_value
};
void sai_reinit()
{
SWSS_LOG_ENTER();
clearDB();
sai_api_uninitialize();
sai_api_initialize(0, (sai_service_method_table_t*)&test_services);
}
void test_sai_initialize()
{
SWSS_LOG_ENTER();
// NOTE: this is just testing whether test application will
// link against libsairedis, this api requires running redis db
// with enabled unix socket
sai_status_t status = sai_api_initialize(0, (sai_service_method_table_t*)&test_services);
// Mock the SAI api
test_next_hop_group_api.create_next_hop_group_member = test_create_next_hop_group_member;
sai_metadata_sai_next_hop_group_api = &test_next_hop_group_api;
created_next_hop_group_member.clear();
ASSERT_SUCCESS("Failed to initialize api");
}
void test_enable_recording()
{
SWSS_LOG_ENTER();
sai_attribute_t attr;
attr.id = SAI_REDIS_SWITCH_ATTR_RECORD;
attr.value.booldata = true;
sai_switch_api_t *sai_switch_api = NULL;
sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);
sai_status_t status = sai_switch_api->set_switch_attribute(SAI_NULL_OBJECT_ID, &attr);
ASSERT_SUCCESS("Failed to enable recording");
}
bool starts_with(const std::string& str, const std::string& substr)
{
SWSS_LOG_ENTER();
return strncmp(str.c_str(), substr.c_str(), substr.size()) == 0;
}
sai_status_t processBulkEvent(
_In_ sai_common_api_t api,
_In_ const swss::KeyOpFieldsValuesTuple &kco)
{
SWSS_LOG_ENTER();
return SAI_STATUS_FAILURE;
}
void bulk_nhgm_consumer_worker()
{
SWSS_LOG_ENTER();
std::string tableName = ASIC_STATE_TABLE;
swss::DBConnector db("ASIC_DB", 0, true);
swss::ConsumerTable c(&db, tableName);
swss::Select cs;
swss::Selectable *selectcs;
int ret = 0;
cs.addSelectable(&c);
while ((ret = cs.select(&selectcs)) == swss::Select::OBJECT)
{
swss::KeyOpFieldsValuesTuple kco;
c.pop(kco);
auto& key = kfvKey(kco);
auto& op = kfvOp(kco);
if (starts_with(key, "SAI_OBJECT_TYPE_SWITCH")) continue;
if (op == "bulkcreate")
{
sai_status_t status = SAI_STATUS_FAILURE;
try
{
status = processBulkEvent((sai_common_api_t)SAI_COMMON_API_BULK_CREATE, kco);
}
catch(std::exception&e)
{
SWSS_LOG_ERROR("got exception: %s", e.what());
}
ASSERT_SUCCESS("Failed to processBulkEvent");
break;
}
}
}
void test_bulk_next_hop_group_member_create()
{
SWSS_LOG_ENTER();
sai_reinit();
// auto consumerThreads = new std::thread(bulk_nhgm_consumer_worker);
sai_status_t status;
sai_next_hop_api_t *sai_next_hop_api = NULL;
sai_next_hop_group_api_t *sai_next_hop_group_api = NULL;
sai_switch_api_t *sai_switch_api = NULL;
sai_lag_api_t *sai_lag_api = NULL;
sai_router_interface_api_t *sai_rif_api = NULL;
sai_virtual_router_api_t * sai_virtual_router_api = NULL;
sai_api_query(SAI_API_NEXT_HOP, (void**)&sai_next_hop_api);
sai_api_query(SAI_API_NEXT_HOP_GROUP, (void**)&sai_next_hop_group_api);
sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);
sai_api_query(SAI_API_ROUTER_INTERFACE, (void **)&sai_rif_api);
sai_api_query(SAI_API_LAG, (void**)&sai_lag_api);
sai_api_query(SAI_API_VIRTUAL_ROUTER, (void**)&sai_virtual_router_api);
uint32_t count = 3;
std::vector<sai_route_entry_t> routes;
std::vector<sai_attribute_t> attrs;
sai_attribute_t swattr;
swattr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
swattr.value.booldata = true;
sai_object_id_t switch_id;
status = sai_switch_api->create_switch(&switch_id, 1, &swattr);
ASSERT_SUCCESS("Failed to create switch");
std::vector<std::vector<sai_attribute_t>> nhgm_attrs;
std::vector<const sai_attribute_t *> nhgm_attrs_array;
std::vector<uint32_t> nhgm_attrs_count;
sai_object_id_t hopgroup_vid;
sai_attribute_t nhgattr;
nhgattr.id = SAI_NEXT_HOP_GROUP_ATTR_TYPE;
nhgattr.value.s32 = SAI_NEXT_HOP_GROUP_TYPE_ECMP;
status = sai_next_hop_group_api->create_next_hop_group(&hopgroup_vid, switch_id, 1,&nhgattr);
ASSERT_SUCCESS("failed to create next hop group");
// virtual router
sai_object_id_t vr;
status = sai_virtual_router_api->create_virtual_router(&vr, switch_id, 0, NULL);
ASSERT_SUCCESS("failed to create virtual router");
// create lag
sai_object_id_t lag;
status = sai_lag_api->create_lag(&lag, switch_id, 0, NULL);
// create router interface
sai_object_id_t rif;
sai_attribute_t rifattr[3];
rifattr[0].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID;
rifattr[0].value.oid = vr;
rifattr[1].id = SAI_ROUTER_INTERFACE_ATTR_TYPE;
rifattr[1].value.s32 = SAI_ROUTER_INTERFACE_TYPE_PORT;
rifattr[2].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID;
rifattr[2].value.oid = lag;
status = sai_rif_api->create_router_interface(&rif, switch_id, 3, rifattr);
ASSERT_SUCCESS("Failed to create router interface");
for (uint32_t i = 0; i < count; ++i)
{
sai_object_id_t hop_vid;
sai_attribute_t nhattr[3] = { };
nhattr[0].id = SAI_NEXT_HOP_ATTR_TYPE;
nhattr[0].value.s32 = SAI_NEXT_HOP_TYPE_IP;
nhattr[1].id = SAI_NEXT_HOP_ATTR_IP;
nhattr[1].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
nhattr[1].value.ipaddr.addr.ip4 = 0x10000001 + count;
nhattr[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID;
nhattr[2].value.oid = rif;
status = sai_next_hop_api->create_next_hop(&hop_vid, switch_id, 3, nhattr);
ASSERT_SUCCESS("failed to create next hop");
std::vector<sai_attribute_t> list(2);
sai_attribute_t &attr1 = list[0];
sai_attribute_t &attr2 = list[1];
attr1.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
attr1.value.oid = hopgroup_vid;
attr2.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID;
attr2.value.oid = hop_vid;
nhgm_attrs.push_back(list);
nhgm_attrs_count.push_back(2);
}
for (size_t j = 0; j < nhgm_attrs.size(); j++)
{
nhgm_attrs_array.push_back(nhgm_attrs[j].data());
}
std::vector<sai_status_t> statuses(count);
std::vector<sai_object_id_t> object_id(count);
sai_next_hop_group_api->create_next_hop_group_members(switch_id, count, nhgm_attrs_count.data(), nhgm_attrs_array.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, object_id.data(), statuses.data());
ASSERT_SUCCESS("Failed to bulk create nhgm");
for (size_t j = 0; j < statuses.size(); j++)
{
status = statuses[j];
ASSERT_SUCCESS("Failed to create nhgm # %zu", j);
}
return ;
//consumerThreads->join();
//delete consumerThreads;
// check the created nhgm
for (size_t i = 0; i < created_next_hop_group_member.size(); i++)
{
auto& created = created_next_hop_group_member[i];
auto& created_attrs = std::get<2>(created);
assert(created_attrs.size() == 2);
assert(created_attrs[1].value.oid == nhgm_attrs[i][1].value.oid);
}
status = sai_next_hop_group_api->remove_next_hop_group_members(count, object_id.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to bulk remove nhgm");
}
void test_bulk_next_hop_create()
{
SWSS_LOG_ENTER();
sai_reinit();
sai_status_t status;
sai_next_hop_api_t *sai_next_hop_api = NULL;
sai_switch_api_t *sai_switch_api = NULL;
sai_lag_api_t *sai_lag_api = NULL;
sai_router_interface_api_t *sai_rif_api = NULL;
sai_virtual_router_api_t * sai_virtual_router_api = NULL;
sai_api_query(SAI_API_NEXT_HOP, (void**)&sai_next_hop_api);
sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);
sai_api_query(SAI_API_ROUTER_INTERFACE, (void **)&sai_rif_api);
sai_api_query(SAI_API_LAG, (void**)&sai_lag_api);
sai_api_query(SAI_API_VIRTUAL_ROUTER, (void**)&sai_virtual_router_api);
uint32_t count = 3;
std::vector<sai_attribute_t> attrs;
sai_attribute_t swattr;
swattr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
swattr.value.booldata = true;
sai_object_id_t switch_id;
status = sai_switch_api->create_switch(&switch_id, 1, &swattr);
ASSERT_SUCCESS("Failed to create switch");
// virtual router
sai_object_id_t vr;
status = sai_virtual_router_api->create_virtual_router(&vr, switch_id, 0, NULL);
ASSERT_SUCCESS("failed to create virtual router");
// create lag
sai_object_id_t lag;
status = sai_lag_api->create_lag(&lag, switch_id, 0, NULL);
// create router interface
sai_object_id_t rif;
sai_attribute_t rifattr[3];
rifattr[0].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID;
rifattr[0].value.oid = vr;
rifattr[1].id = SAI_ROUTER_INTERFACE_ATTR_TYPE;
rifattr[1].value.s32 = SAI_ROUTER_INTERFACE_TYPE_PORT;
rifattr[2].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID;
rifattr[2].value.oid = lag;
status = sai_rif_api->create_router_interface(&rif, switch_id, 3, rifattr);
ASSERT_SUCCESS("Failed to create router interface");
std::vector<std::vector<sai_attribute_t>> nh_attrs;
std::vector<const sai_attribute_t *> nh_attrs_array;
std::vector<uint32_t> nh_attrs_count;
for (uint32_t i = 0; i < count; ++i)
{
std::vector<sai_attribute_t> list(3);
sai_attribute_t &nhattr0 = list[0];
sai_attribute_t &nhattr1 = list[1];
sai_attribute_t &nhattr2 = list[2];
nhattr0.id = SAI_NEXT_HOP_ATTR_TYPE;
nhattr0.value.s32 = SAI_NEXT_HOP_TYPE_IP;
nhattr1.id = SAI_NEXT_HOP_ATTR_IP;
nhattr1.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
nhattr1.value.ipaddr.addr.ip4 = 0x10000001;
nhattr2.id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID;
nhattr2.value.oid = rif;
nh_attrs.push_back(list);
nh_attrs_count.push_back(3);
}
for (size_t j = 0; j < nh_attrs.size(); j++)
{
nh_attrs_array.push_back(nh_attrs[j].data());
}
std::vector<sai_status_t> statuses(count);
std::vector<sai_object_id_t> object_id(count);
sai_next_hop_api->create_next_hops(switch_id, count, nh_attrs_count.data(), nh_attrs_array.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, object_id.data(), statuses.data());
ASSERT_SUCCESS("Failed to bulk create nh");
for (size_t j = 0; j < statuses.size(); j++)
{
status = statuses[j];
ASSERT_SUCCESS("Failed to create nh # %zu", j);
}
statuses.clear();
status = sai_next_hop_api->remove_next_hops(count, object_id.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to bulk remove nh");
for (size_t j = 0; j < statuses.size(); j++)
{
status = statuses[j];
ASSERT_SUCCESS("Failed to remove nh # %zu", j);
}
}
void test_bulk_fdb_create()
{
SWSS_LOG_ENTER();
sai_reinit();
sai_status_t status;
sai_switch_api_t *sai_switch_api = NULL;
sai_lag_api_t *sai_lag_api = NULL;
sai_fdb_api_t *sai_fdb_api = NULL;
sai_bridge_api_t *sai_bridge_api = NULL;
sai_virtual_router_api_t * sai_virtual_router_api = NULL;
sai_api_query(SAI_API_BRIDGE, (void**)&sai_bridge_api);
sai_api_query(SAI_API_FDB, (void**)&sai_fdb_api);
sai_api_query(SAI_API_LAG, (void**)&sai_lag_api);
sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);
sai_api_query(SAI_API_VIRTUAL_ROUTER, (void**)&sai_virtual_router_api);
uint32_t count = 3;
std::vector<sai_fdb_entry_t> fdbs;
uint32_t index = 15;
sai_attribute_t swattr;
swattr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
swattr.value.booldata = true;
sai_object_id_t switch_id;
status = sai_switch_api->create_switch(&switch_id, 1, &swattr);
ASSERT_SUCCESS("Failed to create switch");
std::vector<std::vector<sai_attribute_t>> fdb_attrs;
std::vector<const sai_attribute_t *> fdb_attrs_array;
std::vector<uint32_t> fdb_attrs_count;
for (uint32_t i = index; i < index + count; ++i)
{
// virtual router
sai_object_id_t vr;
status = sai_virtual_router_api->create_virtual_router(&vr, switch_id, 0, NULL);
ASSERT_SUCCESS("failed to create virtual router");
// bridge
sai_object_id_t bridge;
sai_attribute_t battr;
battr.id = SAI_BRIDGE_ATTR_TYPE;
battr.value.s32 = SAI_BRIDGE_TYPE_1Q;
status = sai_bridge_api->create_bridge(&bridge, switch_id, 1, &battr);
ASSERT_SUCCESS("failed to create bridge");
sai_object_id_t lag;
status = sai_lag_api->create_lag(&lag, switch_id, 0, NULL);
ASSERT_SUCCESS("failed to create lag");
// bridge port
sai_object_id_t bridge_port;
sai_attribute_t bpattr[2];
bpattr[0].id = SAI_BRIDGE_PORT_ATTR_TYPE;
bpattr[0].value.s32 = SAI_BRIDGE_PORT_TYPE_PORT;
bpattr[1].id = SAI_BRIDGE_PORT_ATTR_PORT_ID;
bpattr[1].value.oid = lag;
status = sai_bridge_api->create_bridge_port(&bridge_port, switch_id, 2, bpattr);
ASSERT_SUCCESS("failed to create bridge port");
sai_fdb_entry_t fdb_entry;
fdb_entry.switch_id = switch_id;
memset(fdb_entry.mac_address, 0, sizeof(sai_mac_t));
fdb_entry.mac_address[0] = 0xD;
fdb_entry.bv_id = bridge;
fdbs.push_back(fdb_entry);
std::vector<sai_attribute_t> attrs;
sai_attribute_t attr;
attr.id = SAI_FDB_ENTRY_ATTR_TYPE;
attr.value.s32 = (i % 2) ? SAI_FDB_ENTRY_TYPE_DYNAMIC : SAI_FDB_ENTRY_TYPE_STATIC;
attrs.push_back(attr);
attr.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID;
attr.value.oid = bridge_port;
attrs.push_back(attr);
attr.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION;
attr.value.s32 = SAI_PACKET_ACTION_FORWARD;
attrs.push_back(attr);
fdb_attrs.push_back(attrs);
fdb_attrs_count.push_back((unsigned int)attrs.size());
}
for (size_t j = 0; j < fdb_attrs.size(); j++)
{
fdb_attrs_array.push_back(fdb_attrs[j].data());
}
std::vector<sai_status_t> statuses(count);
status = sai_fdb_api->create_fdb_entries(count, fdbs.data(), fdb_attrs_count.data(), (const sai_attribute_t**)fdb_attrs_array.data()
, SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to create fdb");
for (size_t j = 0; j < statuses.size(); j++)
{
status = statuses[j];
ASSERT_SUCCESS("Failed to create fdb # %zu", j);
}
// Remove fdb entry
status = sai_fdb_api->remove_fdb_entries(count, fdbs.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to bulk remove fdb entry");
}
void test_bulk_route_set()
{
SWSS_LOG_ENTER();
sai_reinit();
sai_status_t status;
sai_route_api_t *sai_route_api = NULL;
sai_switch_api_t *sai_switch_api = NULL;
sai_virtual_router_api_t * sai_virtual_router_api = NULL;
sai_next_hop_api_t *sai_next_hop_api = NULL;
sai_lag_api_t *sai_lag_api = NULL;
sai_router_interface_api_t *sai_rif_api = NULL;
sai_api_query(SAI_API_ROUTE, (void**)&sai_route_api);
sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);
sai_api_query(SAI_API_VIRTUAL_ROUTER, (void**)&sai_virtual_router_api);
sai_api_query(SAI_API_NEXT_HOP, (void**)&sai_next_hop_api);
sai_api_query(SAI_API_ROUTER_INTERFACE, (void **)&sai_rif_api);
sai_api_query(SAI_API_LAG, (void**)&sai_lag_api);
uint32_t count = 3;
std::vector<sai_route_entry_t> routes;
std::vector<sai_attribute_t> attrs;
uint32_t index = 15;
sai_attribute_t swattr;
swattr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
swattr.value.booldata = true;
sai_object_id_t switch_id;
status = sai_switch_api->create_switch(&switch_id, 1, &swattr);
ASSERT_SUCCESS("Failed to create switch");
std::vector<std::vector<sai_attribute_t>> route_attrs;
std::vector<const sai_attribute_t *> route_attrs_array;
std::vector<uint32_t> route_attrs_count;
for (uint32_t i = index; i < index + count; ++i)
{
sai_route_entry_t route_entry;
// virtual router
sai_object_id_t vr;
status = sai_virtual_router_api->create_virtual_router(&vr, switch_id, 0, NULL);
ASSERT_SUCCESS("failed to create virtual router");
// create lag
sai_object_id_t lag;
status = sai_lag_api->create_lag(&lag, switch_id, 0, NULL);
// create router interface
sai_object_id_t rif;
sai_attribute_t rifattr[3];
rifattr[0].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID;
rifattr[0].value.oid = vr;
rifattr[1].id = SAI_ROUTER_INTERFACE_ATTR_TYPE;
rifattr[1].value.s32 = SAI_ROUTER_INTERFACE_TYPE_PORT;
rifattr[2].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID;
rifattr[2].value.oid = lag;
status = sai_rif_api->create_router_interface(&rif, switch_id, 3, rifattr);
ASSERT_SUCCESS("Failed to create router interface");
// next hop
sai_object_id_t hop;
sai_attribute_t nhattr[3] = { };
nhattr[0].id = SAI_NEXT_HOP_ATTR_TYPE;
nhattr[0].value.s32 = SAI_NEXT_HOP_TYPE_IP;
nhattr[1].id = SAI_NEXT_HOP_ATTR_IP;
nhattr[1].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
nhattr[1].value.ipaddr.addr.ip4 = 0x10000001;
nhattr[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID;
nhattr[2].value.oid = rif;
status = sai_next_hop_api->create_next_hop(&hop, switch_id, 3, nhattr);
ASSERT_SUCCESS("failed to create next hop");
route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
route_entry.destination.addr.ip4 = htonl(0x0a000000 | i);
route_entry.destination.mask.ip4 = htonl(0xffffffff);
route_entry.vr_id = vr;
route_entry.switch_id = switch_id;
route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
routes.push_back(route_entry);
std::vector<sai_attribute_t> list(2);
sai_attribute_t &attr1 = list[0];
sai_attribute_t &attr2 = list[1];
attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID;
attr1.value.oid = hop;
attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION;
attr2.value.s32 = SAI_PACKET_ACTION_FORWARD;
route_attrs.push_back(list);
route_attrs_count.push_back(2);
}
for (size_t j = 0; j < route_attrs.size(); j++)
{
route_attrs_array.push_back(route_attrs[j].data());
}
std::vector<sai_status_t> statuses(count);
status = sai_route_api->create_route_entries(count, routes.data(), route_attrs_count.data(), route_attrs_array.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to create route");
for (size_t j = 0; j < statuses.size(); j++)
{
status = statuses[j];
ASSERT_SUCCESS("Failed to create route # %zu", j);
}
for (uint32_t i = index; i < index + count; ++i)
{
sai_attribute_t attr;
attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION;
attr.value.s32 = SAI_PACKET_ACTION_DROP;
status = sai_route_api->set_route_entry_attribute(&routes[i - index], &attr);
attrs.push_back(attr);
ASSERT_SUCCESS("Failed to set route");
}
statuses.clear();
statuses.resize(attrs.size());
for (auto &attr: attrs)
{
attr.value.s32 = SAI_PACKET_ACTION_FORWARD;
}
status = sai_route_api->set_route_entries_attribute(
count,
routes.data(),
attrs.data(),
SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR,
statuses.data());
ASSERT_SUCCESS("Failed to bulk set route");
for (auto s: statuses)
{
status = s;
ASSERT_SUCCESS("Failed to bulk set route on one of the routes");
}
// TODO we need to add consumer producer test here to see
// if after consume we get pop we get expected parameters
// TODO in async mode this api will always return success
// Remove route entry
status = sai_route_api->remove_route_entries(count, routes.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to bulk remove route entry");
}
void test_bulk_neighbor_set()
{
SWSS_LOG_ENTER();
sai_reinit();
sai_status_t status;
sai_neighbor_api_t *sai_neighbor_api = NULL;
sai_switch_api_t *sai_switch_api = NULL;
sai_virtual_router_api_t * sai_virtual_router_api = NULL;
sai_lag_api_t *sai_lag_api = NULL;
sai_router_interface_api_t *sai_rif_api = NULL;
sai_api_query(SAI_API_NEIGHBOR, (void**)&sai_neighbor_api);
sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);
sai_api_query(SAI_API_VIRTUAL_ROUTER, (void**)&sai_virtual_router_api);
sai_api_query(SAI_API_ROUTER_INTERFACE, (void **)&sai_rif_api);
sai_api_query(SAI_API_LAG, (void**)&sai_lag_api);
uint32_t count = 3;
std::vector<sai_neighbor_entry_t> neighbors;
std::vector<sai_attribute_t> attrs;
sai_attribute_t swattr;
swattr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
swattr.value.booldata = true;
sai_object_id_t switch_id;
status = sai_switch_api->create_switch(&switch_id, 1, &swattr);
ASSERT_SUCCESS("Failed to create switch");
std::vector<std::vector<sai_attribute_t>> neighbor_attrs;
std::vector<const sai_attribute_t *> neighbor_attrs_array;
std::vector<uint32_t> neighbor_attrs_count;
for (uint32_t i = 0; i < count; ++i)
{
sai_neighbor_entry_t neighbor_entry;
// virtual router
sai_object_id_t vr;
status = sai_virtual_router_api->create_virtual_router(&vr, switch_id, 0, NULL);
ASSERT_SUCCESS("failed to create virtual router");
// create lag
sai_object_id_t lag;
status = sai_lag_api->create_lag(&lag, switch_id, 0, NULL);
// create router interface
sai_object_id_t rif;
sai_attribute_t rifattr[3];
rifattr[0].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID;
rifattr[0].value.oid = vr;
rifattr[1].id = SAI_ROUTER_INTERFACE_ATTR_TYPE;
rifattr[1].value.s32 = SAI_ROUTER_INTERFACE_TYPE_PORT;
rifattr[2].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID;
rifattr[2].value.oid = lag;
status = sai_rif_api->create_router_interface(&rif, switch_id, 3, rifattr);
ASSERT_SUCCESS("Failed to create router interface");
neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
neighbor_entry.ip_address.addr.ip4 = 0x10000001 + i;
neighbor_entry.rif_id = rif;
neighbor_entry.switch_id = switch_id;
neighbors.push_back(neighbor_entry);
std::vector<sai_attribute_t> list(1);
sai_attribute_t &attr = list[0];
sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
attr.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS;
memcpy(attr.value.mac, mac, 6);
neighbor_attrs.push_back(list);
neighbor_attrs_count.push_back(1);
}
for (size_t j = 0; j < neighbor_attrs.size(); j++)
{
neighbor_attrs_array.push_back(neighbor_attrs[j].data());
}
std::vector<sai_status_t> statuses(count);
status = sai_neighbor_api->create_neighbor_entries(count, neighbors.data(), neighbor_attrs_count.data(), neighbor_attrs_array.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to create neighbor");
for (size_t j = 0; j < statuses.size(); j++)
{
status = statuses[j];
ASSERT_SUCCESS("Failed to create neighbor # %zu", j);
}
for (uint32_t i = 0; i < count; ++i)
{
sai_attribute_t attr;
attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION;
attr.value.s32 = SAI_PACKET_ACTION_FORWARD;
status = sai_neighbor_api->set_neighbor_entry_attribute(&neighbors[i], &attr);
attrs.push_back(attr);
ASSERT_SUCCESS("Failed to set neighbor");
}
statuses.clear();
statuses.resize(attrs.size());
for (auto &attr: attrs)
{
attr.value.s32 = SAI_PACKET_ACTION_FORWARD;
}
status = sai_neighbor_api->set_neighbor_entries_attribute(
count,
neighbors.data(),
attrs.data(),
SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR,
statuses.data());
ASSERT_SUCCESS("Failed to bulk set neighbor");
for (auto s: statuses)
{
status = s;
ASSERT_SUCCESS("Failed to bulk set neighbor on one of the neighbors");
}
status = sai_neighbor_api->remove_neighbor_entries(count, neighbors.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, statuses.data());
ASSERT_SUCCESS("Failed to bulk remove neighbor entry");
}
void syncdThread()
{
SWSS_LOG_ENTER();
MetadataLogger::initialize();
auto vendorSai = std::make_shared<VendorSai>();
bool isWarmStart = false;
auto commandLineOptions = std::make_shared<CommandLineOptions>();
commandLineOptions->m_enableTempView = false;
commandLineOptions->m_enableUnittests = false;
commandLineOptions->m_disableExitSleep = true;
commandLineOptions->m_profileMapFile = "testprofile.ini";
auto syncd = std::make_shared<Syncd>(vendorSai, commandLineOptions, isWarmStart);
g_syncd_obj = syncd;
SWSS_LOG_WARN("starting run");
syncd->run();
}
void test_invoke_dump()
{
SWSS_LOG_ENTER();
clearDB();
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);
auto syncd = std::make_shared<std::thread>(syncdThread);
syncd->detach();
sai_attribute_t attr;
attr.id = SAI_REDIS_SWITCH_ATTR_NOTIFY_SYNCD;
attr.value.s32 = SAI_REDIS_NOTIFY_SYNCD_INVOKE_DUMP;
auto sairedis = std::make_shared<sairedis::Sai>();
sai_status_t status = sairedis->apiInitialize(0, &test_services);
CHECK_STATUS(status);
status = sairedis->set(SAI_OBJECT_TYPE_SWITCH, SAI_NULL_OBJECT_ID, &attr);
ASSERT_SUCCESS("Failed to invoke dump");
assert(mockCallArg == SAI_FAILURE_DUMP_SCRIPT);
attr.id = SAI_REDIS_SWITCH_ATTR_NOTIFY_SYNCD;
attr.value.s32 = SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW;
status = sairedis->set(SAI_OBJECT_TYPE_SWITCH, SAI_NULL_OBJECT_ID, &attr);
ASSERT_SUCCESS("Notify syncd failed");
}
void test_watchdog_timer_clock_rollback()
{
SWSS_LOG_ENTER();
const int64_t WARN_TIMESPAN_USEC = 30 * 1000000;
const uint8_t ROLLBACK_TIME_SEC = 5;
const uint8_t LONG_RUNNING_API_TIME_SEC = 3;
// take note of current time
struct timeval currentTime;
gettimeofday(¤tTime, NULL);
// start watchdog timer
TimerWatchdog twd(WARN_TIMESPAN_USEC);
twd.setStartTime();
// roll back time by ROLLBACK_TIME_SEC
currentTime.tv_sec -= ROLLBACK_TIME_SEC;
assert(settimeofday(¤tTime, NULL) == 0);
// Simulate long running API
sleep(LONG_RUNNING_API_TIME_SEC);
twd.setEndTime();
}
void test_query_stats_capability_query()
{
SWSS_LOG_ENTER();
MetadataLogger::initialize();
sai_object_id_t switch_id = 0x21000000000000;
auto switchIdStr = sai_serialize_object_id(switch_id);
auto objectTypeStr = sai_serialize_object_type(SAI_OBJECT_TYPE_QUEUE);
const std::string list_size = std::to_string(1);
const std::string op = "stats_capability_query";
const std::vector<swss::FieldValueTuple> entry =
{
swss::FieldValueTuple("OBJECT_TYPE", objectTypeStr),
swss::FieldValueTuple("LIST_SIZE", list_size)
};
auto consumer = sairedis::RedisSelectableChannel(
g_db1,
ASIC_STATE_TABLE,
REDIS_TABLE_GETRESPONSE,
TEMP_PREFIX,
false);
consumer.set(switchIdStr, entry, op);
sleep(1);
g_syncd_obj->processEvent(consumer);
}
int main()
{
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);
SWSS_LOG_ENTER();
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE);
try
{
test_sai_initialize();
// g_syncMode = true;
test_enable_recording();
test_bulk_next_hop_group_member_create();
test_bulk_next_hop_create();
test_bulk_fdb_create();
test_bulk_neighbor_set();
test_bulk_route_set();
sai_api_uninitialize();
//test_watchdog_timer_clock_rollback();
test_invoke_dump();
test_query_stats_capability_query();
printf("\n[ %s ]\n\n", sai_serialize_status(SAI_STATUS_SUCCESS).c_str());
}
catch (const std::exception &e)
{
SWSS_LOG_ERROR("exception: %s", e.what());
printf("\n[ %s ]\n\n%s\n\n", sai_serialize_status(SAI_STATUS_FAILURE).c_str(), e.what());
exit(EXIT_FAILURE);
}
return 0;
}