void helperCheckCpuId()
{
    SWSS_LOG_ENTER();

    sai_object_id_t cpuId = saiGetCpuId();

    sai_object_id_t redisCpuId = redisGetCpuId();

    if (redisCpuId == SAI_NULL_OBJECT_ID)
    {
        redisSetDummyAsicStateForRealObjectId(cpuId);

        SWSS_LOG_INFO("redis cpu id is not defined yet");

        redisSetCpuId(cpuId);

        redisCpuId = cpuId;
    }

    if (cpuId != redisCpuId)
    {
        // if this happens, we need to remap VIDTORID and RIDTOVID
        SWSS_LOG_ERROR("FIXME: cpu id differs: %llx vs %llx, ids must be remapped", cpuId, redisCpuId);

        exit(EXIT_FAILURE);
    }
}
void helperCheckVirtualRouterId()
{
    SWSS_LOG_ENTER();

    sai_object_id_t vrId = saiGetDefaultVirtualRouter();

    sai_object_id_t redisVrId = redisGetDefaultVirtualRouterId();

    if (redisVrId == SAI_NULL_OBJECT_ID)
    {
        redisSetDummyAsicStateForRealObjectId(vrId);

        SWSS_LOG_INFO("redis default virtual router id is not defined yet");

        redisSetDefaultVirtualRouterId(vrId);

        redisVrId = vrId;
    }

    if (vrId != redisVrId)
    {
        // if this happens, we need to remap VIDTORID and RIDTOVID
        SWSS_LOG_ERROR("FIXME: default virtual router id differs: %llx vs %llx, ids must be remapped", vrId, redisVrId);

        exit(EXIT_FAILURE);
    }
}
static sai_status_t create_port_list()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create port list");

    // TODO this is static, when we start to "create/remove" ports
    // we need to update this list since it's dynamic

    sai_attribute_t attr;

    sai_object_id_t switch_object_id = ss->getSwitchId();

    uint32_t port_count = (uint32_t)port_list.size();

    attr.id = SAI_SWITCH_ATTR_PORT_LIST;
    attr.value.objlist.count = port_count;
    attr.value.objlist.list = port_list.data();

    CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr));

    attr.id = SAI_SWITCH_ATTR_PORT_NUMBER;
    attr.value.u32 = port_count;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr);
}
Beispiel #4
0
void WatermarkOrch::doTask(SelectableTimer &timer)
{
    SWSS_LOG_ENTER();

    if (m_pg_ids.empty())
    {
        init_pg_ids();
    }

    if (m_multicast_queue_ids.empty() and m_unicast_queue_ids.empty())
    {
        init_queue_ids();
    }

    if (&timer == m_telemetryTimer)
    {
        /* If the interval was changed */
        auto intervT = timespec { .tv_sec = m_telemetryInterval , .tv_nsec = 0 };
        m_telemetryTimer->setInterval(intervT);
        m_telemetryTimer->reset();

        clearSingleWm(m_periodicWatermarkTable.get(), "SAI_INGRESS_PRIORITY_GROUP_STAT_XOFF_ROOM_WATERMARK_BYTES", m_pg_ids);
        clearSingleWm(m_periodicWatermarkTable.get(), "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES", m_pg_ids);
        clearSingleWm(m_periodicWatermarkTable.get(), "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES", m_unicast_queue_ids);
        clearSingleWm(m_periodicWatermarkTable.get(), "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES", m_multicast_queue_ids);
        SWSS_LOG_INFO("Periodic watermark cleared by timer!");
    }
}
void processFdbEntriesForAging()
{
    SWSS_LOG_ENTER();

    if (!g_recursive_mutex.try_lock())
    {
        return;
    }

    SWSS_LOG_INFO("fdb infos to process: %zu", g_fdb_info_set.size());

    uint32_t current = (uint32_t)time(NULL);

    // find aged fdb entries

    for (auto it = g_fdb_info_set.begin(); it != g_fdb_info_set.end();)
    {
        sai_attribute_t attr;

        attr.id = SAI_SWITCH_ATTR_FDB_AGING_TIME;

        sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_SWITCH, it->fdb_entry.switch_id, 1, &attr);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_WARN("failed to get FDB aging time for switch %s",
                    sai_serialize_object_id(it->fdb_entry.switch_id).c_str());

            ++it;
            continue;
        }

        uint32_t aging_time = attr.value.u32;

        if (aging_time == 0)
        {
            // aging is disabled
            ++it;
            continue;
        }

        if ((current - it->timestamp) >= aging_time)
        {
            fdb_info_t fi = *it;

            processFdbInfo(fi, SAI_FDB_EVENT_AGED);

            it = g_fdb_info_set.erase(it);
        }
        else
        {
            ++it;
        }
    }

    g_recursive_mutex.unlock();
}
Beispiel #6
0
sai_object_id_t translate_rid_to_vid(
        _In_ sai_object_id_t rid)
{
    SWSS_LOG_ENTER();

    if (rid == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_DEBUG("translated RID null to VID null");

        return SAI_NULL_OBJECT_ID;
    }

    sai_object_id_t vid;

    std::string str_rid;
    std::string str_vid;

    sai_serialize_primitive(rid, str_rid);

    auto pvid = g_redisClient->hget(RIDTOVID, str_rid);

    if (pvid != NULL)
    {
        // object exists
        str_vid = *pvid;

        int index = 0;
        sai_deserialize_primitive(str_vid, index, vid);

        SWSS_LOG_DEBUG("translated RID %llx to VID %llx", rid, vid);

        return vid;
    }

    SWSS_LOG_INFO("spotted new RID %llx", rid);

    sai_object_type_t object_type = sai_object_type_query(rid);

    if (object_type == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("sai_object_type_query returned NULL type for RID %llx", rid);

        exit(EXIT_FAILURE);
    }

    vid = redis_create_virtual_object_id(object_type);

    SWSS_LOG_DEBUG("translated RID %llx to VID %llx", rid, vid);

    sai_serialize_primitive(vid, str_vid);

    g_redisClient->hset(RIDTOVID, str_rid, str_vid);
    g_redisClient->hset(VIDTORID, str_vid, str_rid);

    return vid;
}
static sai_status_t set_maximum_number_of_childs_per_scheduler_group()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create switch src mac address");

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP;
    attr.value.u32 = 16;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr);
}
static sai_status_t set_default_notifications()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create defaultr notifications");

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY;
    attr.value.ptr = NULL;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr);
}
static sai_status_t set_number_of_ecmp_groups()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("set number of ecmp groups");

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS;
    attr.value.u32 = 512;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr);
}
static sai_status_t create_scheduler_groups()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create scheduler groups");

    uint32_t port_sgs_count = 13; // brcm default

    // NOTE: this is only static data, to keep track of this
    // we would need to create actual objects and keep them
    // in respected objects, we need to move in to that
    // solution when we will start using different "profiles"
    // currently this is good enough

    for (const auto &port_id : port_list)
    {
        sai_attribute_t attr;

        attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS;
        attr.value.u32 = port_sgs_count;

        CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr));

        // scheduler groups per port

        std::vector<sai_object_id_t> sgs;

        for (uint32_t i = 0; i < port_sgs_count; ++i)
        {
            sai_object_id_t sg_id;

            CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_SCHEDULER_GROUP, &sg_id, ss->getSwitchId(), 0, NULL));

            sgs.push_back(sg_id);
        }

        attr.id = SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST;
        attr.value.objlist.count = port_sgs_count;
        attr.value.objlist.list = sgs.data();

        CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr));

        CHECK_STATUS(create_scheduler_group_tree(sgs, port_id));
    }

    // SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT // sched_groups + count
    // scheduler group are organized in tree and on the bottom there are queues
    // order matters in returning api
    return SAI_STATUS_SUCCESS;
}
Beispiel #11
0
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;
}
Beispiel #12
0
const char* profile_get_value(
        _In_ sai_switch_profile_id_t profile_id,
        _In_ const char* variable)
{
    SWSS_LOG_ENTER();

    if (variable == NULL)
    {
        SWSS_LOG_WARN("variable is null");
        return NULL;
    }

    auto it = gProfileMap.find(variable);

    if (it == gProfileMap.end())
    {
        SWSS_LOG_INFO("%s: NULL", variable);
        return NULL;
    }

    SWSS_LOG_INFO("%s: %s", variable, it->second.c_str());

    return it->second.c_str();
}
Beispiel #13
0
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");

        gProfileIter = gProfileMap.begin();
        return 0;
    }

    if (variable == NULL)
    {
        SWSS_LOG_WARN("variable is null");
        return -1;
    }

    if (gProfileIter == gProfileMap.end())
    {
        SWSS_LOG_INFO("iterator reached end");
        return -1;
    }

    *variable = gProfileIter->first.c_str();
    *value = gProfileIter->second.c_str();

    SWSS_LOG_INFO("key: %s:%s", *variable, *value);

    gProfileIter++;

    return 0;
}
void helperCheckLaneMap()
{
    SWSS_LOG_ENTER();

    auto redisLaneMap = redisGetLaneMap();

    auto laneMap = saiGetHardwareLaneMap();

    if (redisLaneMap.size() == 0)
    {
        SWSS_LOG_INFO("no lanes defined in redis, seems like it is first syncd start");

        // TODO put ports to db ?
        redisSaveLaneMap(laneMap);

        redisLaneMap = laneMap; // copy
    }

    if (laneMap.size() != redisLaneMap.size())
    {
        SWSS_LOG_ERROR("lanes map size differ: %lu vs %lu", laneMap.size(), redisLaneMap.size());

        exit(EXIT_FAILURE);
    }

    for (auto kv: laneMap)
    {
        sai_uint32_t lane = kv.first;
        sai_object_id_t portId = kv.second;

        if (redisLaneMap.find(lane) == redisLaneMap.end())
        {
            SWSS_LOG_ERROR("lane %u not found in redis", lane);

            exit(EXIT_FAILURE);
        }

        if (redisLaneMap[lane] != portId)
        {
            // if this happens, we need to remap VIDTORID and RIDTOVID
            SWSS_LOG_ERROR("FIXME: lane port id differs: %llx vs %llx, port ids must be remapped", portId, redisLaneMap[lane]);

            exit(EXIT_FAILURE);
        }
    }
}
static sai_status_t create_acl_entry_min_prio()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create acl entry min prio");

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY;
    attr.value.u32 = 1;

    CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr));

    attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY;
    attr.value.u32 = 16000;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr);
}
static sai_status_t create_default_virtual_router()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create default virtual router");

    sai_object_id_t switch_object_id = ss->getSwitchId();

    sai_object_id_t virtual_router_id;

    CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &virtual_router_id, switch_object_id, 0, NULL));

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID;
    attr.value.oid = virtual_router_id;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr);
}
static sai_status_t create_default_stp_instance()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create default stp instance");

    sai_object_id_t stp_instance_id;

    sai_object_id_t switch_object_id = ss->getSwitchId();

    CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_STP, &stp_instance_id, switch_object_id, 0, NULL));

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID;
    attr.value.oid = stp_instance_id;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr);
}
static sai_status_t set_switch_mac_address()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create switch src mac address");

    sai_attribute_t attr;

    attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS;

    attr.value.mac[0] = 0x11;
    attr.value.mac[1] = 0x22;
    attr.value.mac[2] = 0x33;
    attr.value.mac[3] = 0x44;
    attr.value.mac[4] = 0x55;
    attr.value.mac[5] = 0x66;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr);
}
static sai_status_t create_qos_queues()
{
    SWSS_LOG_ENTER();

    // TODO queues size may change when we will modify queue or ports

    SWSS_LOG_INFO("create qos queues");

    sai_object_id_t switch_object_id = ss->getSwitchId();

    // 10 in and 10 out queues per port
    const uint32_t port_qos_queues_count = 20;

    for (auto &port_id : port_list)
    {
        std::vector<sai_object_id_t> queues;

        for (uint32_t i = 0; i < port_qos_queues_count; ++i)
        {
            sai_object_id_t queue_id;

            CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_QUEUE, &queue_id, switch_object_id, 0, NULL));

            queues.push_back(queue_id);
        }

        sai_attribute_t attr;

        attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES;
        attr.value.u32 = port_qos_queues_count;

        CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr));

        attr.id = SAI_PORT_ATTR_QOS_QUEUE_LIST;
        attr.value.objlist.count = port_qos_queues_count;
        attr.value.objlist.list = queues.data();

        CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr));
    }

    return SAI_STATUS_SUCCESS;
}
static sai_status_t create_ingress_priority_groups()
{
    SWSS_LOG_ENTER();

    // TODO prioirity groups size may change when we will modify pg or ports

    SWSS_LOG_INFO("create priority groups");

    sai_object_id_t switch_object_id = ss->getSwitchId();

    //
    const uint32_t port_pgs_count = 8;

    for (auto &port_id : port_list)
    {
        std::vector<sai_object_id_t> pgs;

        for (uint32_t i = 0; i < port_pgs_count; ++i)
        {
            sai_object_id_t pg_id;

            CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, &pg_id, switch_object_id, 0, NULL));

            pgs.push_back(pg_id);
        }

        sai_attribute_t attr;

        attr.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS;
        attr.value.u32 = port_pgs_count;

        CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr));

        attr.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST;
        attr.value.objlist.count = port_pgs_count;
        attr.value.objlist.list = pgs.data();

        CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr));
    }

    return SAI_STATUS_SUCCESS;
}
static sai_status_t create_default_trap_group()
{
    SWSS_LOG_ENTER();

    sai_object_id_t switch_object_id = ss->getSwitchId();

    SWSS_LOG_INFO("create default trap group");

    sai_object_id_t trap_group_id;

    CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP, &trap_group_id, switch_object_id, 0, NULL));

    sai_attribute_t attr;

    // populate trap group on switch
    attr.id = SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP;
    attr.value.oid = trap_group_id;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr);
}
static sai_status_t create_default_vlan()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create default vlan");

    sai_attribute_t attr;

    attr.id = SAI_VLAN_ATTR_VLAN_ID;
    attr.value.u16 = DEFAULT_VLAN_NUMBER;

    CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_VLAN, &default_vlan_id, ss->getSwitchId(), 1, &attr));

    /* set default vlan on switch */

    attr.id = SAI_SWITCH_ATTR_DEFAULT_VLAN_ID;
    attr.value.oid = default_vlan_id;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr);
}
void swss::NotificationConsumer::subscribe()
{
    SWSS_LOG_ENTER();

    /* Create new new context to DB */
    if (m_db->getContext()->connection_type == REDIS_CONN_TCP)
        m_subscribe = new DBConnector(m_db->getDB(),
                                      m_db->getContext()->tcp.host,
                                      m_db->getContext()->tcp.port,
                                      NOTIFICATION_SUBSCRIBE_TIMEOUT);
    else
        m_subscribe = new DBConnector(m_db->getDB(),
                                      m_db->getContext()->unix_sock.path,
                                      NOTIFICATION_SUBSCRIBE_TIMEOUT);

    std::string s = "SUBSCRIBE " + m_channel;

    RedisReply r(m_subscribe, s, REDIS_REPLY_ARRAY);

    SWSS_LOG_INFO("subscribed to %s", m_channel.c_str());
}
static sai_status_t create_default_1q_bridge()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create default 1q bridge");

    sai_attribute_t attr;

    attr.id = SAI_BRIDGE_ATTR_TYPE;
    attr.value.s32 = SAI_BRIDGE_TYPE_1Q;

    sai_object_id_t switch_id = ss->getSwitchId();

    sai_object_id_t default_1q_bridge;

    CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_BRIDGE, &default_1q_bridge, switch_id, 1, &attr));

    attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID;
    attr.value.oid = default_1q_bridge;

    return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr);
}
Beispiel #25
0
void handleProfileMap(const std::string& profileMapFile)
{
    SWSS_LOG_ENTER();

    if (profileMapFile.size() == 0)
        return;

    std::ifstream profile(profileMapFile);

    if (!profile.is_open())
    {
        SWSS_LOG_ERROR("failed to open profile map file: %s : %s", profileMapFile.c_str(), strerror(errno));
        exit(EXIT_FAILURE);
    }

    std::string line;

    while(getline(profile, line))
    {
        if (line.size() > 0 && (line[0] == '#' || line[0] == ';'))
            continue;

        size_t pos = line.find("=");

        if (pos == std::string::npos)
        {
            SWSS_LOG_WARN("not found '=' in line %s", line.c_str());
            continue;
        }

        std::string key = line.substr(0, pos);
        std::string value = line.substr(pos + 1);

        gProfileMap[key] = value;

        SWSS_LOG_INFO("insert: %s:%s", key.c_str(), value.c_str());
    }
}
static sai_status_t create_cpu_port()
{
    SWSS_LOG_ENTER();

    SWSS_LOG_INFO("create cpu port");

    sai_attribute_t attr;

    sai_object_id_t switch_id = ss->getSwitchId();

    CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_PORT, &cpu_port_id, switch_id, 0, &attr));

    // populate cpu port object on switch
    attr.id = SAI_SWITCH_ATTR_CPU_PORT;
    attr.value.oid = cpu_port_id;

    CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr));

    // set type on cpu
    attr.id = SAI_PORT_ATTR_TYPE;
    attr.value.s32 = SAI_PORT_TYPE_CPU;

    return vs_generic_set(SAI_OBJECT_TYPE_PORT, cpu_port_id, &attr);
}
sai_status_t handle_generic(
        _In_ sai_object_type_t object_type,
        _In_ const std::string &str_object_id,
        _In_ sai_common_api_t api,
        _In_ uint32_t attr_count,
        _In_ sai_attribute_t *attr_list)
{
    SWSS_LOG_ENTER();

    sai_object_id_t local_id;
    sai_deserialize_object_id(str_object_id, local_id);

    SWSS_LOG_DEBUG("generic %s for %s:%s",
            sai_serialize_common_api(api).c_str(),
            sai_serialize_object_type(object_type).c_str(),
            str_object_id.c_str());

    auto info = sai_metadata_get_object_type_info(object_type);

    sai_object_meta_key_t meta_key;

    meta_key.objecttype = object_type;

    switch (api)
    {
        case SAI_COMMON_API_CREATE:

            {
                sai_object_id_t switch_id = sai_switch_id_query(local_id);

                if (switch_id == SAI_NULL_OBJECT_ID)
                {
                    SWSS_LOG_THROW("invalid switch_id translated from VID %s",
                            sai_serialize_object_id(local_id).c_str());
                }

                if (object_type == SAI_OBJECT_TYPE_SWITCH)
                {
                    update_notifications_pointers(attr_count, attr_list);

                    /*
                     * We are creating switch, in both cases local and redis
                     * switch id is deterministic and should be the same.
                     */
                }
                else
                {
                    /*
                     * When we creating switch, then switch_id parameter is
                     * ignored, but we can't convert it using vid to rid map,
                     * since rid don't exist yet, so skip translate for switch,
                     * but use translate for all other objects.
                     */

                     switch_id = translate_local_to_redis(switch_id);
                }

                sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list);

                if (status == SAI_STATUS_SUCCESS)
                {
                    sai_object_id_t rid = meta_key.objectkey.key.object_id;

                    match_redis_with_rec(rid, local_id);

                    SWSS_LOG_INFO("saved VID %s to RID %s",
                            sai_serialize_object_id(local_id).c_str(),
                            sai_serialize_object_id(rid).c_str());
                }
                else
                {
                    SWSS_LOG_ERROR("failed to create %s",
                            sai_serialize_status(status).c_str());
                }

                return status;
            }

        case SAI_COMMON_API_REMOVE:

            {
                meta_key.objectkey.key.object_id = translate_local_to_redis(local_id);

                return info->remove(&meta_key);
            }

        case SAI_COMMON_API_SET:

            {
                if (object_type == SAI_OBJECT_TYPE_SWITCH)
                {
                    update_notifications_pointers(1, attr_list);
                }

                meta_key.objectkey.key.object_id = translate_local_to_redis(local_id);

                return info->set(&meta_key, attr_list);
            }

        case SAI_COMMON_API_GET:

            {
                meta_key.objectkey.key.object_id = translate_local_to_redis(local_id);

                return info->get(&meta_key, attr_count, attr_list);
            }

        default:
            SWSS_LOG_THROW("generic other apis not implemented");
    }
}
Beispiel #28
0
sai_status_t processEvent(swss::ConsumerTable &consumer)
{
    std::lock_guard<std::mutex> lock(g_mutex);

    SWSS_LOG_ENTER();

    swss::KeyOpFieldsValuesTuple kco;
    consumer.pop(kco);

    const std::string &key = kfvKey(kco);
    const std::string &op = kfvOp(kco);

    std::string str_object_type = key.substr(0, key.find(":"));
    std::string str_object_id = key.substr(key.find(":")+1);

    SWSS_LOG_INFO("key: %s op: %s", key.c_str(), op.c_str());

    sai_common_api_t api = SAI_COMMON_API_MAX;

    if (op == "create")
        api = SAI_COMMON_API_CREATE;
    else if (op == "remove")
        api = SAI_COMMON_API_REMOVE;
    else if (op == "set")
        api = SAI_COMMON_API_SET;
    else if (op == "get")
        api = SAI_COMMON_API_GET;
    else
    {
        if (op != "delget")
            SWSS_LOG_ERROR("api %s is not implemented", op.c_str());

        return SAI_STATUS_NOT_SUPPORTED;
    }

    std::stringstream ss;

    int index = 0;
    sai_object_type_t object_type;
    sai_deserialize_primitive(str_object_type, index, object_type);

    if (object_type >= SAI_OBJECT_TYPE_MAX)
    {
        SWSS_LOG_ERROR("undefined object type %d", object_type);
        return SAI_STATUS_NOT_SUPPORTED;
    }

    const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues(kco);

    SaiAttributeList list(object_type, values, false);

    if (api != SAI_COMMON_API_GET)
        translate_vid_to_rid_list(object_type, list.get_attr_count(), list.get_attr_list());

    sai_attribute_t *attr_list = list.get_attr_list();
    uint32_t attr_count = list.get_attr_count();

    sai_status_t status;
    switch (object_type)
    {
        case SAI_OBJECT_TYPE_FDB:
            status = handle_fdb(str_object_id, api, attr_count, attr_list);
            break;

        case SAI_OBJECT_TYPE_SWITCH:
            status = handle_switch(str_object_id, api, attr_count, attr_list);
            break;

        case SAI_OBJECT_TYPE_NEIGHBOR:
            status = handle_neighbor(str_object_id, api, attr_count, attr_list);
            break;

        case SAI_OBJECT_TYPE_ROUTE:
            status = handle_route(str_object_id, api, attr_count, attr_list);
            break;

        case SAI_OBJECT_TYPE_VLAN:
            status = handle_vlan(str_object_id, api, attr_count, attr_list);
            break;

        case SAI_OBJECT_TYPE_TRAP:
            status = handle_trap(str_object_id, api, attr_count, attr_list);
            break;

        default:
            status = handle_generic(object_type, str_object_id, api, attr_count, attr_list);
            break;
    }

    if (api == SAI_COMMON_API_GET)
    {
        internal_syncd_get_send(object_type, status, attr_count, attr_list);
    }
    else if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to execute api: %s: %d", op.c_str(), status);

        exit(EXIT_FAILURE);
    }

    return status;
}
Beispiel #29
0
sai_status_t handle_generic(
        _In_ sai_object_type_t object_type,
        _In_ std::string &str_object_id,
        _In_ sai_common_api_t api,
        _In_ uint32_t attr_count,
        _In_ sai_attribute_t *attr_list)
{
    SWSS_LOG_ENTER();

    int index = 0;
    sai_object_id_t object_id;
    sai_deserialize_primitive(str_object_id, index, object_id);

    SWSS_LOG_DEBUG("common generic api: %d", api);

    switch(api)
    {
        case SAI_COMMON_API_CREATE:
            {
                SWSS_LOG_DEBUG("generic create for object type %x", object_type);

                create_fn create = common_create[object_type];

                if (create == NULL)
                {
                    SWSS_LOG_ERROR("create function is not defined for object type %x", object_type);
                    exit(EXIT_FAILURE);
                }

                sai_object_id_t real_object_id;
                sai_status_t status = create(&real_object_id, attr_count, attr_list);

                if (status == SAI_STATUS_SUCCESS)
                {
                    // object was created so new object id was generated
                    // we need to save virtual id's to redis db

                    std::string str_vid;
                    std::string str_rid;

                    sai_serialize_primitive(object_id, str_vid);
                    sai_serialize_primitive(real_object_id, str_rid);

                    g_redisClient->hset(VIDTORID, str_vid, str_rid);
                    g_redisClient->hset(RIDTOVID, str_rid, str_vid);

                    SWSS_LOG_INFO("saved VID %s to RID %s", str_vid.c_str(), str_rid.c_str());
                }
                else
                {
                    SWSS_LOG_ERROR("failed to create %d", status);
                }

                return status;
            }

        case SAI_COMMON_API_REMOVE:
            {
                SWSS_LOG_DEBUG("generic remove for object type %x", object_type);

                remove_fn remove = common_remove[object_type];

                if (remove == NULL)
                {
                    SWSS_LOG_ERROR("remove function is not defined for object type %x", object_type);
                    exit(EXIT_FAILURE);
                }

                sai_object_id_t rid = translate_vid_to_rid(object_id);

                std::string str_vid;
                sai_serialize_primitive(object_id, str_vid);

                std::string str_rid;
                sai_serialize_primitive(rid, str_rid);

                g_redisClient->hdel(VIDTORID, str_vid);
                g_redisClient->hdel(RIDTOVID, str_rid);

                return remove(rid);
            }

        case SAI_COMMON_API_SET:
            {
                SWSS_LOG_DEBUG("generic set for object type %x", object_type);

                set_attribute_fn set = common_set_attribute[object_type];

                if (set == NULL)
                {
                    SWSS_LOG_ERROR("set function is not defined for object type %x", object_type);
                    exit(EXIT_FAILURE);
                }

                sai_object_id_t rid = translate_vid_to_rid(object_id);

                return set(rid, attr_list);
            }

        case SAI_COMMON_API_GET:
            {
                SWSS_LOG_DEBUG("generic get for object type %x", object_type);

                get_attribute_fn get = common_get_attribute[object_type];

                if (get == NULL)
                {
                    SWSS_LOG_ERROR("get function is not defined for object type %x", object_type);
                    exit(EXIT_FAILURE);
                }

                sai_object_id_t rid = translate_vid_to_rid(object_id);

                return get(rid, attr_count, attr_list);
            }

        default:
            SWSS_LOG_ERROR("generic other apis not implemented");
            exit(EXIT_FAILURE);
    }
}
void channelOpSetStats(
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    SWSS_LOG_ENTER();

    // NOTE: we need to find stats for specific object, later SAI already have
    // this feature and this search could be optimized here:
    // https://github.com/opencomputeproject/SAI/commit/acc83933ff21c68e8ef10c9826de45807fdc0438

    sai_object_id_t oid;

    sai_deserialize_object_id(key, oid);

    sai_object_type_t ot = sai_object_type_query(oid);

    if (ot == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("invalid object id: %s", key.c_str());
        return;
    }

    sai_object_id_t switch_id = sai_switch_id_query(oid);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("unable to get switch_id from oid: %s", key.c_str());
        return;
    }

    /*
     * Check if object for statistics was created and exists on switch.
     */

    auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(ot);

    auto it = objectHash.find(key.c_str());

    if (it == objectHash.end())
    {
        SWSS_LOG_ERROR("object not found: %s", key.c_str());
        return;
    }

    /*
     * Check if object for statistics have statistic map created, if not
     * create empty map.
     */

    auto &countersMap = g_switch_state_map.at(switch_id)->countersMap;

    auto mapit = countersMap.find(key);

    if (mapit == countersMap.end())
        countersMap[key] = std::map<int,uint64_t>();

    /*
     * Find stats enum based on object type.  In new metadata we have enum on
     * object type, but here we need to find it manually enum is in format
     * "sai_" + object_type + "_stat_t"
     */

    std::string lower_ot = sai_serialize_object_type(ot).substr(16);  // 16 = skip "SAI_OBJECT_TYPE_"

    std::transform(lower_ot.begin(), lower_ot.end(), lower_ot.begin(), ::tolower);

    std::string stat_enum_name = "sai_" + lower_ot + "_stat_t";

    const sai_enum_metadata_t* statenum = NULL;

    for (size_t i = 0; i < sai_metadata_all_enums_count; ++i)
    {
        if (sai_metadata_all_enums[i]->name == stat_enum_name)
        {
            SWSS_LOG_INFO("found enum %s", stat_enum_name.c_str());
            // found
            statenum = sai_metadata_all_enums[i];
            break;
        }
    }

    if (statenum == NULL)
    {
        SWSS_LOG_ERROR("failed to find stat enum: %s", stat_enum_name.c_str());
        return;
    }

    for (auto v: values)
    {
        // value format: stat_enum_name:uint64

        auto name = fvField(v);

        uint64_t value;

        if (sscanf(fvValue(v).c_str(), "%lu", &value) != 1)
        {
            SWSS_LOG_ERROR("failed to deserialize %s as couner value uint64_t", fvValue(v).c_str());
        }

        // linear search

        int enumvalue = -1;

        for (size_t i = 0; i < statenum->valuescount; ++i)
        {
            if (statenum->valuesnames[i] == name)
            {
                enumvalue = statenum->values[i];
                break;
            }
        }

        if (enumvalue == -1)
        {
            SWSS_LOG_ERROR("failed to find enum value: %s", name.c_str());
            continue;
        }

        SWSS_LOG_DEBUG("writting %s = %lu on %s", name.c_str(), value, key.c_str());

        countersMap.at(key)[enumvalue] = value;
    }
}