コード例 #1
0
/**
 * Function Description:
 *    @brief adds a decap tunnel to ASIC_DB
 *
 * Arguments:
 *    @param[in] type - type of tunnel
 *    @param[in] dst_ip - destination ip address to decap
 *    @param[in] src_ip - source ip address to decap
 *    @param[in] dscp - dscp mode (uniform/pipe)
 *    @param[in] ecn - ecn mode (copy_from_outer/standard)
 *    @param[in] ttl - ttl mode (uniform/pipe)
 *
 * Return Values:
 *    @return true on success and false if there's an error
 */
bool TunnelDecapOrch::addDecapTunnel(string key, string type, IpAddresses dst_ip, IpAddress src_ip, string dscp, string ecn, string ttl)
{

    SWSS_LOG_ENTER();

    sai_status_t status;

    // adding tunnel attributes to array and writing to ASIC_DB
    sai_attribute_t attr;
    vector<sai_attribute_t> tunnel_attrs;
    sai_object_id_t overlayIfId;

    // create the overlay router interface to create a LOOPBACK type router interface (decap)
    vector<sai_attribute_t> overlay_intf_attrs;

    sai_attribute_t overlay_intf_attr;
    overlay_intf_attr.id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID;
    overlay_intf_attr.value.oid = gVirtualRouterId;
    overlay_intf_attrs.push_back(overlay_intf_attr);

    overlay_intf_attr.id = SAI_ROUTER_INTERFACE_ATTR_TYPE;
    overlay_intf_attr.value.s32 = SAI_ROUTER_INTERFACE_TYPE_LOOPBACK;
    overlay_intf_attrs.push_back(overlay_intf_attr);

    status = sai_router_intfs_api->create_router_interface(&overlayIfId, gSwitchId, (uint32_t)overlay_intf_attrs.size(), overlay_intf_attrs.data());
    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("Failed to create overlay router interface %d", status);
        return false;
    }

    SWSS_LOG_NOTICE("Create overlay loopback router interface oid:%lx", overlayIfId);

    // tunnel type (only ipinip for now)
    attr.id = SAI_TUNNEL_ATTR_TYPE;
    attr.value.s32 = SAI_TUNNEL_TYPE_IPINIP;
    tunnel_attrs.push_back(attr);
    attr.id = SAI_TUNNEL_ATTR_OVERLAY_INTERFACE;
    attr.value.oid = overlayIfId;
    tunnel_attrs.push_back(attr);
    attr.id = SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE;
    attr.value.oid = gUnderlayIfId;
    tunnel_attrs.push_back(attr);

    // tunnel src ip
    attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP;
    copy(attr.value.ipaddr, src_ip.to_string());
    tunnel_attrs.push_back(attr);

    // decap ecn mode (copy from outer/standard)
    attr.id = SAI_TUNNEL_ATTR_DECAP_ECN_MODE;
    if (ecn == "copy_from_outer")
    {
        attr.value.s32 = SAI_TUNNEL_DECAP_ECN_MODE_COPY_FROM_OUTER;
    }
    else if (ecn == "standard")
    {
        attr.value.s32 = SAI_TUNNEL_DECAP_ECN_MODE_STANDARD;
    }
    tunnel_attrs.push_back(attr);

    // ttl mode (uniform/pipe)
    attr.id = SAI_TUNNEL_ATTR_DECAP_TTL_MODE;
    if (ttl == "uniform")
    {
        attr.value.s32 = SAI_TUNNEL_TTL_MODE_UNIFORM_MODEL;
    }
    else if (ttl == "pipe")
    {
        attr.value.s32 = SAI_TUNNEL_TTL_MODE_PIPE_MODEL;
    }
    tunnel_attrs.push_back(attr);

    // dscp mode (uniform/pipe)
    attr.id = SAI_TUNNEL_ATTR_DECAP_DSCP_MODE;
    if (dscp == "uniform")
    {
        attr.value.s32 = SAI_TUNNEL_DSCP_MODE_UNIFORM_MODEL;
    }
    else if (dscp == "pipe")
    {
        attr.value.s32 = SAI_TUNNEL_DSCP_MODE_PIPE_MODEL;
    }
    tunnel_attrs.push_back(attr);

    // write attributes to ASIC_DB
    sai_object_id_t tunnel_id;
    status = sai_tunnel_api->create_tunnel(&tunnel_id, gSwitchId, (uint32_t)tunnel_attrs.size(), tunnel_attrs.data());
    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("Failed to create tunnel");
        return false;
    }

    tunnelTable[key] = { tunnel_id, {} };

    // TODO:
    // there should also be "business logic" for netbouncer in the "tunnel application" code, which is a different source file and daemon process

    // create a decap tunnel entry for every ip
    if (!addDecapTunnelTermEntries(key, dst_ip, tunnel_id))
    {
        return false;
    }

    return true;
}
コード例 #2
0
void TunnelDecapOrch::doTask(Consumer& consumer)
{
    SWSS_LOG_ENTER();

    if (!gPortsOrch->isInitDone())
    {
        return;
    }

    auto it = consumer.m_toSync.begin();
    while (it != consumer.m_toSync.end())
    {
        KeyOpFieldsValuesTuple t = it->second;

        string key = kfvKey(t);
        string op = kfvOp(t);

        IpAddresses ip_addresses;
        IpAddress src_ip;
        string tunnel_type;
        string dscp_mode;
        string ecn_mode;
        string ttl_mode;
        bool valid = true;

        // checking to see if the tunnel already exists
        bool exists = (tunnelTable.find(key) != tunnelTable.end());

        if (op == SET_COMMAND)
        {

            for (auto i : kfvFieldsValues(t))
            {
                if (fvField(i) == "tunnel_type")
                {
                    tunnel_type = fvValue(i);
                    if (tunnel_type != "IPINIP")
                    {
                        SWSS_LOG_ERROR("Invalid tunnel type %s", tunnel_type.c_str());
                        valid = false;
                        break;
                    }
                }
                else if (fvField(i) == "dst_ip")
                {
                    try
                    {
                        ip_addresses = IpAddresses(fvValue(i));
                    }
                    catch (const std::invalid_argument &e)
                    {
                        SWSS_LOG_ERROR("%s", e.what());
                        valid = false;
                        break;
                    }
                    if (exists)
                    {
                        setIpAttribute(key, ip_addresses, tunnelTable.find(key)->second.tunnel_id);
                    }
                }
                else if (fvField(i) == "src_ip")
                {
                    try
                    {
                        src_ip = IpAddress(fvValue(i));
                    }
                    catch (const std::invalid_argument &e)
                    {
                        SWSS_LOG_ERROR("%s", e.what());
                        valid = false;
                        break;
                    }
                    if (exists)
                    {
                        SWSS_LOG_ERROR("cannot modify src ip for existing tunnel");
                    }
                }
                else if (fvField(i) == "dscp_mode")
                {
                    dscp_mode = fvValue(i);
                    if (dscp_mode != "uniform" && dscp_mode != "pipe")
                    {
                        SWSS_LOG_ERROR("Invalid dscp mode %s\n", dscp_mode.c_str());
                        valid = false;
                        break;
                    }
                    if (exists)
                    {
                        setTunnelAttribute(fvField(i), dscp_mode, tunnelTable.find(key)->second.tunnel_id);
                    }
                }
                else if (fvField(i) == "ecn_mode")
                {
                    ecn_mode = fvValue(i);
                    if (ecn_mode != "copy_from_outer" && ecn_mode != "standard")
                    {
                        SWSS_LOG_ERROR("Invalid ecn mode %s\n", ecn_mode.c_str());
                        valid = false;
                        break;
                    }
                    if (exists)
                    {
                        setTunnelAttribute(fvField(i), ecn_mode, tunnelTable.find(key)->second.tunnel_id);
                    }
                }
                else if (fvField(i) == "ttl_mode")
                {
                    ttl_mode = fvValue(i);
                    if (ttl_mode != "uniform" && ttl_mode != "pipe")
                    {
                        SWSS_LOG_ERROR("Invalid ttl mode %s\n", ttl_mode.c_str());
                        valid = false;
                        break;
                    }
                    if (exists)
                    {
                        setTunnelAttribute(fvField(i), ttl_mode, tunnelTable.find(key)->second.tunnel_id);
                    }
                }
            }

            // create new tunnel if it doesn't exists already
            if (valid && !exists)
            {
                if (addDecapTunnel(key, tunnel_type, ip_addresses, src_ip, dscp_mode, ecn_mode, ttl_mode))
                {
                    SWSS_LOG_NOTICE("Tunnel(s) added to ASIC_DB.");
                }
                else
                {
                    SWSS_LOG_ERROR("Failed to add tunnels to ASIC_DB.");
                }
            }
        }

        if (op == DEL_COMMAND)
        {
            if (exists)
            {
                removeDecapTunnel(key);
            }
            else
            {
                SWSS_LOG_ERROR("Tunnel cannot be removed since it doesn't exist.");
            }
        }

        it = consumer.m_toSync.erase(it);
    }
}
コード例 #3
0
void getPortLaneMap(
        _Inout_ std::vector<std::vector<uint32_t>> &laneMap)
{
    SWSS_LOG_ENTER();

    laneMap.clear();

    for (auto v: g_laneMap)
    {
        size_t s = v.size();

        if (s != 1 && s != 2 && s != 4)
        {
            SWSS_LOG_THROW("invald number of lanes for interface: %zu", s);
        }

        laneMap.push_back(v);
    }

    if (g_laneMap.size())
    {
        SWSS_LOG_NOTICE("got port lane map with %zu interfaces", laneMap.size());
        return;
    }

    const uint32_t default_port_count = 32;

    sai_uint32_t default_lanes[] = {
        29,30,31,32,
        25,26,27,28,
        37,38,39,40,
        33,34,35,36,
        41,42,43,44,
        45,46,47,48,
        5,6,7,8,
        1,2,3,4,
        9,10,11,12,
        13,14,15,16,
        21,22,23,24,
        17,18,19,20,
        49,50,51,52,
        53,54,55,56,
        61,62,63,64,
        57,58,59,60,
        65,66,67,68,
        69,70,71,72,
        77,78,79,80,
        73,74,75,76,
        105,106,107,108,
        109,110,111,112,
        117,118,119,120,
        113,114,115,116,
        121,122,123,124,
        125,126,127,128,
        85,86,87,88,
        81,82,83,84,
        89,90,91,92,
        93,94,95,96,
        97,98,99,100,
        101,102,103,104
    };

    // populate default lane map

    for (size_t i = 0; i < default_port_count; i++)
    {
        std::vector<uint32_t> portLanes;

        for(int j = 0; j < 4; j++)
            portLanes.push_back(default_lanes[4*i + j]);

        laneMap.push_back(portLanes);
    }

    SWSS_LOG_NOTICE("populated default port lane map with %zu interfaces", laneMap.size());
}
コード例 #4
0
sai_status_t sai_api_initialize(
        _In_ uint64_t flags,
        _In_ const sai_service_method_table_t *service_method_table)
{
    MUTEX();

    SWSS_LOG_ENTER();

    if (g_api_initialized)
    {
        SWSS_LOG_ERROR("api already initialized");

        return SAI_STATUS_FAILURE;
    }

    if ((service_method_table == NULL) ||
            (service_method_table->profile_get_next_value == NULL) ||
            (service_method_table->profile_get_value == NULL))
    {
        SWSS_LOG_ERROR("invalid service_method_table handle passed to SAI API initialize");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    memcpy(&g_service_method_table, service_method_table, sizeof(g_service_method_table));

    // TODO maybe this query should be done right before switch create
    const char *type = service_method_table->profile_get_value(0, SAI_KEY_VS_SWITCH_TYPE);

    if (type == NULL)
    {
        SWSS_LOG_ERROR("failed to obtain service method table value: %s", SAI_KEY_VS_SWITCH_TYPE);

        return SAI_STATUS_FAILURE;
    }

    g_interface_lane_map_file = service_method_table->profile_get_value(0, SAI_KEY_VS_INTERFACE_LANE_MAP_FILE);

    load_interface_lane_map();

    g_boot_type             = service_method_table->profile_get_value(0, SAI_KEY_BOOT_TYPE);
    g_warm_boot_read_file   = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE);
    g_warm_boot_write_file  = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE);

    std::string bt = (g_boot_type == NULL) ? "cold" : g_boot_type;

    if (bt == "cold" || bt == "0")
    {
        g_vs_boot_type = SAI_VS_COLD_BOOT;
    }
    else if (bt == "warm" || bt == "1")
    {
        g_vs_boot_type = SAI_VS_WARM_BOOT;
    }
    else if (bt == "fast" || bt == "2")
    {
        g_vs_boot_type = SAI_VS_FAST_BOOT;
    }
    else
    {
        SWSS_LOG_ERROR("unsupported boot type: %s", g_boot_type);

        return SAI_STATUS_FAILURE;
    }

    std::string strType = type;

    if (strType == SAI_VALUE_VS_SWITCH_TYPE_BCM56850)
    {
        g_vs_switch_type = SAI_VS_SWITCH_TYPE_BCM56850;
    }
    else if (strType == SAI_VALUE_VS_SWITCH_TYPE_MLNX2700)
    {
        g_vs_switch_type = SAI_VS_SWITCH_TYPE_MLNX2700;
    }
    else
    {
        SWSS_LOG_ERROR("unknown switch type: '%s'", type);

        return SAI_STATUS_FAILURE;
    }

    const char *use_tap_dev = service_method_table->profile_get_value(0, SAI_KEY_VS_HOSTIF_USE_TAP_DEVICE);

    g_vs_hostif_use_tap_device = use_tap_dev != NULL && strcmp(use_tap_dev, "true") == 0;

    SWSS_LOG_NOTICE("hostif use TAP device: %s",
            g_vs_hostif_use_tap_device ? "true" : "false");

    if (flags != 0)
    {
        SWSS_LOG_ERROR("invalid flags passed to SAI API initialize");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    clear_local_state();

    g_dbNtf = std::make_shared<swss::DBConnector>(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0);
    g_unittestChannelNotificationConsumer = std::make_shared<swss::NotificationConsumer>(g_dbNtf.get(), SAI_VS_UNITTEST_CHANNEL);

    g_unittestChannelRun = true;

    g_unittestChannelThread = std::make_shared<std::thread>(std::thread(unittestChannelThreadProc));

    g_fdb_info_set.clear();

    g_fdbAgingThreadRun = true;

    // TODO should this be moved to create switch and SwitchState?
    g_fdbAgingThread = std::make_shared<std::thread>(std::thread(fdbAgingThreadProc));

    g_api_initialized = true;

    return SAI_STATUS_SUCCESS;
}
コード例 #5
0
void channelOpSetReadOnlyAttribute(
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    SWSS_LOG_ENTER();

    for (const auto &v: values)
    {
        SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
    }

    if (values.size() != 1)
    {
        SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size());
        return;
    }

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

    sai_object_type_t object_type;
    sai_deserialize_object_type(str_object_type, object_type);

    if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX)
    {
        SWSS_LOG_ERROR("invalid object type: %d", object_type);
        return;
    }

    auto info = sai_metadata_get_object_type_info(object_type);

    if (info->isnonobjectid)
    {
        SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str());
        return;
    }

    sai_object_id_t object_id;

    sai_deserialize_object_id(str_object_id, object_id);

    sai_object_type_t ot = sai_object_type_query(object_id);

    if (ot != object_type)
    {
        SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s",
                str_object_type.c_str(), sai_serialize_object_type(ot).c_str());
        return;
    }

    sai_object_id_t switch_id = sai_switch_id_query(object_id);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str());
        return;
    }

    // oid is validated and we got switch id

    const std::string &str_attr_id = fvField(values.at(0));
    const std::string &str_attr_value = fvValue(values.at(0));

    auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());

    if (meta == NULL)
    {
        SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str());
        return;
    }

    if (meta->objecttype != ot)
    {
        SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s",
                str_attr_id.c_str(), sai_serialize_object_type(ot).c_str());
        return;
    }

    // we got attr metadata

    sai_attribute_t attr;

    attr.id = meta->attrid;

    sai_deserialize_attr_value(str_attr_value, *meta, attr);

    SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str());

    sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str());
        return;
    }

    sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } };

    status = info->set(&meta_key, &attr);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to set %s to %s on %s",
                str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
    }
    else
    {
        SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s",
                str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
    }

    sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
}
コード例 #6
0
void load_interface_lane_map()
{
    SWSS_LOG_ENTER();

    if (g_interface_lane_map_file == NULL)
    {
        SWSS_LOG_NOTICE("no interface lane map");
        return;
    }

    std::ifstream lanemap(g_interface_lane_map_file);

    if (!lanemap.is_open())
    {
        SWSS_LOG_ERROR("failed to open lane map file: %s", g_interface_lane_map_file);
        return;
    }

    std::string line;

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

        auto tokens = swss::tokenize(line, ':');

        if (tokens.size() != 2)
        {
            SWSS_LOG_ERROR("expected 2 tokens in line %s, got %zu", line.c_str(), tokens.size());
            continue;
        }

        auto ifname = tokens.at(0);
        auto lanes = tokens.at(1);

        if (!check_ifname(ifname))
        {
            continue;
        }

        if (g_ifname_to_lanes.find(ifname) != g_ifname_to_lanes.end())
        {
            SWSS_LOG_ERROR("interface %s was already defined", ifname.c_str());
            continue;
        }

        tokens = swss::tokenize(lanes,',');

        size_t n = tokens.size();

        if (n != 1 && n != 2 && n != 4)
        {
            SWSS_LOG_ERROR("invalid number of lanes (%zu) assigned to interface %s", n, ifname.c_str());
            continue;
        }

        std::vector<uint32_t> lanevec;

        for (auto l: tokens)
        {
            uint32_t lanenumber;
            if (sscanf(l.c_str(), "%u", &lanenumber) != 1)
            {
                SWSS_LOG_ERROR("failed to parse lane number: %s", l.c_str());
                continue;
            }

            if (g_lane_to_ifname.find(lanenumber) != g_lane_to_ifname.end())
            {
                SWSS_LOG_ERROR("lane number %u used on %s was already defined on %s",
                        lanenumber,
                        ifname.c_str(),
                        g_lane_to_ifname.at(lanenumber).c_str());
                continue;
            }

            lanevec.push_back(lanenumber);
            g_lane_order.push_back(lanenumber);

            g_lane_to_ifname[lanenumber] = ifname;
        }

        g_ifname_to_lanes[ifname] = lanevec;
        g_laneMap.push_back(lanevec);
    }

    SWSS_LOG_NOTICE("loaded %zu lanes and %zu interfaces", g_lane_to_ifname.size(), g_ifname_to_lanes.size());
}
コード例 #7
0
void handleUnittestChannelOp(
        _In_ const std::string &op,
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    /*
     * Since we will access and modify DB we need to be under mutex.
     *
     * NOTE: since this unittest channel is handled in thread, then that means
     * there is a DELAY from producer and consumer thread in VS, so if user
     * will set value on the specific READ_ONLY value he should wait for some
     * time until that value will be propagated to virtual switch.
     */

    MUTEX();

    SWSS_LOG_ENTER();

    SWSS_LOG_NOTICE("read only SET: op = %s, key = %s", op.c_str(), key.c_str());

    if (op == SAI_VS_UNITTEST_ENABLE_UNITTESTS)
    {
        bool enable = (key == "true");

        meta_unittests_enable(enable);
    }
    else if (op == SAI_VS_UNITTEST_SET_RO_OP)
    {
        for (const auto &v: values)
        {
            SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
        }

        if (values.size() != 1)
        {
            SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size());
            return;
        }

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

        sai_object_type_t object_type;
        sai_deserialize_object_type(str_object_type, object_type);

        if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_MAX)
        {
            SWSS_LOG_ERROR("invalid object type: %d", object_type);
            return;
        }

        auto info = sai_metadata_get_object_type_info(object_type);

        if (info->isnonobjectid)
        {
            SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str());
            return;
        }

        sai_object_id_t object_id;

        sai_deserialize_object_id(str_object_id, object_id);

        sai_object_type_t ot = sai_object_type_query(object_id);

        if (ot != object_type)
        {
            SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s",
                    str_object_type.c_str(), sai_serialize_object_type(ot).c_str());
            return;
        }

        sai_object_id_t switch_id = sai_switch_id_query(object_id);

        if (switch_id == SAI_NULL_OBJECT_ID)
        {
            SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str());
            return;
        }

        // oid is validated and we got switch id

        const std::string &str_attr_id = fvField(values.at(0));
        const std::string &str_attr_value = fvValue(values.at(0));

        auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());

        if (meta == NULL)
        {
            SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str());
            return;
        }

        if (meta->objecttype != ot)
        {
            SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s",
                    str_attr_id.c_str(), sai_serialize_object_type(ot).c_str());
            return;
        }

        // we got attr metadata

        sai_attribute_t attr;

        attr.id = meta->attrid;

        sai_deserialize_attr_value(str_attr_value, *meta, attr);

        SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str());

        sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str());
            return;
        }

        sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } };

        status = info->set(&meta_key, &attr);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_ERROR("failed to set %s to %s on %s",
                    str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
        }
        else
        {
            SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s",
                    str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
        }

        sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
    }
    else
    {
コード例 #8
0
cmdOptions handleCmdLine(int argc, char **argv)
{
    SWSS_LOG_ENTER();

    cmdOptions options = {};

    const int defaultCountersThreadIntervalInSeconds = 1;

    options.countersThreadIntervalInSeconds = defaultCountersThreadIntervalInSeconds;

#ifdef SAITHRIFT
    options.run_rpc_server = false;
    const char* const optstring = "dNt:p:i:rm:h";
#else
    const char* const optstring = "dNt:p:i:h";
#endif // SAITHRIFT

    while(true)
    {
        static struct option long_options[] =
        {
            { "diag",             no_argument,       0, 'd' },
            { "nocounters",       no_argument,       0, 'N' },
            { "startType",        required_argument, 0, 't' },
            { "profile",          required_argument, 0, 'p' },
            { "countersInterval", required_argument, 0, 'i' },
            { "help",             no_argument,       0, 'h' },
#ifdef SAITHRIFT
            { "rpcserver",        no_argument,       0, 'r' },
            { "portmap",          required_argument, 0, 'm' },
#endif // SAITHRIFT
            { 0,                  0,                 0,  0  }
        };

        int option_index = 0;

        int c = getopt_long(argc, argv, optstring, long_options, &option_index);

        if (c == -1)
            break;

        switch (c)
        {
            case 'N':
                SWSS_LOG_NOTICE("disable counters thread");
                options.disableCountersThread = true;
                break;

            case 'd':
                SWSS_LOG_NOTICE("enable diag shell");
                options.diagShell = true;
                break;

            case 'p':
                SWSS_LOG_NOTICE("profile map file: %s", optarg);
                options.profileMapFile = std::string(optarg);
                break;

            case 'i':
                {
                    SWSS_LOG_NOTICE("counters thread interval: %s", optarg);

                    int interval = std::stoi(std::string(optarg));

                    if (interval == 0)
                    {
                        // use zero interval to disable counters thread
                        options.disableCountersThread = true;
                    }
                    else
                    {
                        options.countersThreadIntervalInSeconds =
                            std::max(defaultCountersThreadIntervalInSeconds, interval);
                    }

                    break;
                }

            case 't':
                SWSS_LOG_NOTICE("start type: %s", optarg);
                if (std::string(optarg) == "cold")
                {
                    options.startType = SAI_COLD_BOOT;
                }
                else if (std::string(optarg) == "warm")
                {
                    options.startType = SAI_WARM_BOOT;
                }
                else if (std::string(optarg) == "fast")
                {
                    options.startType = SAI_FAST_BOOT;
                }
                else
                {
                    SWSS_LOG_ERROR("unknown start type %s", optarg);
                    exit(EXIT_FAILURE);
                }
                break;

#ifdef SAITHRIFT
            case 'r':
                SWSS_LOG_NOTICE("enable rpc server");
                options.run_rpc_server = true;
                break;
            case 'm':
                SWSS_LOG_NOTICE("port map file: %s", optarg);
                options.portMapFile = std::string(optarg);
                break;
#endif // SAITHRIFT

            case 'h':
                printUsage();
                exit(EXIT_SUCCESS);

            case '?':
                SWSS_LOG_WARN("unknown option %c", optopt);
                printUsage();
                exit(EXIT_FAILURE);

            default:
                SWSS_LOG_ERROR("getopt_long failure");
                exit(EXIT_FAILURE);
        }
    }

    return options;
}
コード例 #9
0
ファイル: intfsorch.cpp プロジェクト: krambn/sonic-swss
void IntfsOrch::doTask(Consumer &consumer)
{
    SWSS_LOG_ENTER();

    if (consumer.m_toSync.empty())
        return;

    if (!m_portsOrch->isInitDone())
        return;

    auto it = consumer.m_toSync.begin();
    while (it != consumer.m_toSync.end())
    {
        KeyOpFieldsValuesTuple t = it->second;

        string key = kfvKey(t);
        size_t found = key.find(':');
        if (found == string::npos)
        {
            SWSS_LOG_ERROR("Failed to parse task key %s\n", key.c_str());
            it = consumer.m_toSync.erase(it);
            continue;
        }
        string alias = key.substr(0, found);

        IpPrefix ip_prefix(key.substr(found+1));
        if (!ip_prefix.isV4())
        {
            it = consumer.m_toSync.erase(it);
            continue;
        }

        string op = kfvOp(t);

        if (op == SET_COMMAND)
        {
            /* Duplicate entry */
            if (m_intfs.find(alias) != m_intfs.end() && m_intfs[alias] == ip_prefix.getIp())
            {
                it = consumer.m_toSync.erase(it);
                continue;
            }

            Port p;
            if (!m_portsOrch->getPort(alias, p))
            {
                SWSS_LOG_ERROR("Failed to locate interface %s\n", alias.c_str());
                it = consumer.m_toSync.erase(it);
                continue;
            }

            sai_unicast_route_entry_t unicast_route_entry;
            unicast_route_entry.vr_id = gVirtualRouterId;
            unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
            unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr() & ip_prefix.getMask().getV4Addr();
            unicast_route_entry.destination.mask.ip4 = ip_prefix.getMask().getV4Addr();

            sai_attribute_t attr;
            vector<sai_attribute_t> attrs;

            attr.id = SAI_ROUTE_ATTR_PACKET_ACTION;
            attr.value.s32 = SAI_PACKET_ACTION_FORWARD;
            attrs.push_back(attr);

            attr.id = SAI_ROUTE_ATTR_NEXT_HOP_ID;
            attr.value.oid = p.m_rif_id;
            attrs.push_back(attr);

            sai_status_t status = sai_route_api->create_route(&unicast_route_entry, attrs.size(), attrs.data());
            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("Failed to create subnet route pre:%s %d\n", ip_prefix.to_string().c_str(), status);
                it++;
                continue;
            }
            else
            {
                SWSS_LOG_NOTICE("Create subnet route pre:%s\n", ip_prefix.to_string().c_str());
            }

            unicast_route_entry.vr_id = gVirtualRouterId;
            unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
            unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr();
            unicast_route_entry.destination.mask.ip4 = 0xFFFFFFFF;

            attr.id = SAI_ROUTE_ATTR_PACKET_ACTION;
            attr.value.s32 = SAI_PACKET_ACTION_TRAP;
            status = sai_route_api->create_route(&unicast_route_entry, 1, &attr);
            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("Failed to create packet action trap route ip:%s %d\n", ip_prefix.getIp().to_string().c_str(), status);
                it++;
            }
            else
            {
                SWSS_LOG_NOTICE("Create packet action trap route ip:%s\n", ip_prefix.getIp().to_string().c_str());
                m_intfs[alias] = ip_prefix.getIp();
                it = consumer.m_toSync.erase(it);
            }
        }
        else if (op == DEL_COMMAND)
        {
            Port p;
            if (!m_portsOrch->getPort(alias, p))
            {
                SWSS_LOG_ERROR("Failed to locate interface %s\n", alias.c_str());
                it = consumer.m_toSync.erase(it);
                continue;
            }

            sai_unicast_route_entry_t unicast_route_entry;
            unicast_route_entry.vr_id = gVirtualRouterId;
            unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
            unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr() & ip_prefix.getMask().getV4Addr();
            unicast_route_entry.destination.mask.ip4 = ip_prefix.getMask().getV4Addr();

            sai_status_t status = sai_route_api->remove_route(&unicast_route_entry);
            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("Failed to remove subnet route pre:%s %d\n", ip_prefix.to_string().c_str(), status);
                it++;
                continue;
            }

            unicast_route_entry.vr_id = gVirtualRouterId;
            unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
            unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr();
            unicast_route_entry.destination.mask.ip4 = 0xFFFFFFFF;

            status = sai_route_api->remove_route(&unicast_route_entry);
            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("Failed to remove action trap route ip:%s %d\n", ip_prefix.getIp().to_string().c_str(), status);
                it++;
            }
            else
            {
                SWSS_LOG_NOTICE("Remove packet action trap route ip:%s\n", ip_prefix.getIp().to_string().c_str());
                m_intfs.erase(alias);
                it = consumer.m_toSync.erase(it);
            }
        }
    }
}
コード例 #10
0
sai_status_t sai_bulk_create_route_entry(
        _In_ uint32_t object_count,
        _In_ const sai_route_entry_t *route_entry,
        _In_ const uint32_t *attr_count,
        _In_ const sai_attribute_t **attr_list,
        _In_ sai_bulk_op_error_mode_t mode,
        _Out_ sai_status_t *object_statuses)
{
    std::lock_guard<std::mutex> lock(g_apimutex);

    SWSS_LOG_ENTER();

    if (object_count < 1)
    {
        SWSS_LOG_ERROR("expected at least 1 object to create");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (route_entry == NULL)
    {
        SWSS_LOG_ERROR("route_entry is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (attr_count == NULL)
    {
        SWSS_LOG_ERROR("attr_count is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (attr_list == NULL)
    {
        SWSS_LOG_ERROR("attr_list is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    switch (mode)
    {
        case SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR:
        case SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR:
             // ok
             break;

        default:

             SWSS_LOG_ERROR("invalid bulk operation mode %d", mode);

             return SAI_STATUS_INVALID_PARAMETER;
    }

    if (object_statuses == NULL)
    {
        SWSS_LOG_ERROR("object_statuses is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    std::vector<std::string> serialized_object_ids;

    for (uint32_t idx = 0; idx < object_count; ++idx)
    {
        /*
         * At the beginning set all statuses to not executed.
         */

        object_statuses[idx] = SAI_STATUS_NOT_EXECUTED;

        serialized_object_ids.push_back(
                sai_serialize_route_entry(route_entry[idx]));
    }

    for (uint32_t idx = 0; idx < object_count; ++idx)
    {
        sai_status_t status =
            meta_sai_create_route_entry(
                    &route_entry[idx],
                    attr_count[idx],
                    attr_list[idx],
                    &redis_dummy_create_route_entry);

        object_statuses[idx] = status;

        if (status != SAI_STATUS_SUCCESS)
        {
            // TODO add attr id and value

            SWSS_LOG_ERROR("failed on index %u: %s",
                    idx,
                    serialized_object_ids[idx].c_str());

            if (mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR)
            {
                SWSS_LOG_NOTICE("stop on error since previous operation failed");
                break;
            }
        }
    }

    /*
     * TODO: we need to record operation type
     */

    return internal_redis_bulk_generic_create(
            SAI_OBJECT_TYPE_ROUTE_ENTRY,
            serialized_object_ids,
            attr_count,
            attr_list,
            object_statuses);
}
コード例 #11
0
sai_status_t internal_vs_generic_get(
        _In_ sai_object_type_t object_type,
        _In_ const std::string &serialized_object_id,
        _In_ sai_object_id_t switch_id,
        _In_ uint32_t attr_count,
        _Out_ sai_attribute_t *attr_list)
{
    SWSS_LOG_ENTER();

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

    auto it = objectHash.find(serialized_object_id);

    if (it == objectHash.end())
    {
        SWSS_LOG_ERROR("not found %s:%s",
                sai_serialize_object_type(object_type).c_str(),
                serialized_object_id.c_str());

        return SAI_STATUS_ITEM_NOT_FOUND;
    }

    /*
     * We need reference here since we can potentially update attr hash for RO
     * object.
     */

    AttrHash& attrHash = it->second;

    /*
     * Some of the list query maybe for length, so we can't do
     * normal serialize, maybe with count only.
     */

    sai_status_t final_status = SAI_STATUS_SUCCESS;

    for (uint32_t idx = 0; idx < attr_count; ++idx)
    {
        sai_attr_id_t id = attr_list[idx].id;

        auto meta = sai_metadata_get_attr_metadata(object_type, id);

        if (meta == NULL)
        {
            SWSS_LOG_ERROR("failed to find attribute %d for %s:%s", id,
                    sai_serialize_object_type(object_type).c_str(),
                    serialized_object_id.c_str());

            return SAI_STATUS_FAILURE;
        }

        sai_status_t status;

        if (HAS_FLAG_READ_ONLY(meta->flags))
        {
            /*
             * Read only attributes may require recalculation.
             * Metadata makes sure that non object id's can't have
             * read only attributes. So here is defenetly OID.
             */

            sai_object_id_t oid;
            sai_deserialize_object_id(serialized_object_id, oid);

            status = refresh_read_only(meta, oid, switch_id);

            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("%s read only not implemented on %s",
                        meta->attridname,
                        serialized_object_id.c_str());

                return status;
            }
        }

        auto ait = attrHash.find(meta->attridname);

        if (ait == attrHash.end())
        {
            SWSS_LOG_ERROR("%s not implemented on %s",
                    meta->attridname,
                    serialized_object_id.c_str());

            return SAI_STATUS_NOT_IMPLEMENTED;
        }

        auto attr = ait->second->getAttr();

        status = transfer_attributes(object_type, 1, attr, &attr_list[idx], false);

        if (status == SAI_STATUS_BUFFER_OVERFLOW)
        {
            /*
             * This is considered partial success, since we get correct list
             * length.  Note that other items ARE processes on the list.
             */

            SWSS_LOG_NOTICE("BUFFER_OVERFLOW %s: %s",
                    serialized_object_id.c_str(),
                    meta->attridname);

            /*
             * We still continue processing other attributes for get as long as
             * we only will be getting buffer overflow error.
             */

            final_status = status;
            continue;
        }

        if (status != SAI_STATUS_SUCCESS)
        {
            // all other errors

            SWSS_LOG_ERROR("get failed %s: %s: %s",
                    serialized_object_id.c_str(),
                    meta->attridname,
                    sai_serialize_status(status).c_str());

            return status;
        }
    }

    return final_status;
}
コード例 #12
0
static sai_status_t refresh_bridge_port_list(
        _In_ const sai_attr_metadata_t *meta,
        _In_ sai_object_id_t bridge_id,
        _In_ sai_object_id_t switch_id)
{
    SWSS_LOG_ENTER();

    /*
     * TODO possible issues with vxlan and lag.
     */

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

    sai_attribute_t attr;

    auto m_port_list = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE, SAI_BRIDGE_ATTR_PORT_LIST);
    auto m_port_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
    auto m_bridge_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_BRIDGE_ID);

    /*
     * First get all port's that belong to this bridge id.
     */

    std::map<sai_object_id_t, AttrHash> bridge_port_list_on_bridge_id;

    for (const auto &bp: all_bridge_ports)
    {
        auto it = bp.second.find(m_bridge_id->attridname);

        if (it == bp.second.end())
        {
            continue;
        }

        if (bridge_id == it->second->getAttr()->value.oid)
        {
            /*
             * This bridge port belongs to currently processing bridge ID.
             */

            sai_object_id_t bridge_port;

            sai_deserialize_object_id(bp.first, bridge_port);

            bridge_port_list_on_bridge_id[bridge_port] = bp.second;
        }
    }

    /*
     * Now sort those bridge port id's by port id to be consistent.
     */

    std::vector<sai_object_id_t> bridge_port_list;

    for (const auto &p: port_list)
    {
        for (const auto &bp: bridge_port_list_on_bridge_id)
        {
            auto it = bp.second.find(m_port_id->attridname);

            if (it == bp.second.end())
            {
                SWSS_LOG_THROW("bridge port is missing %s, not supported yet, FIXME", m_port_id->attridname);
            }

            if (p == it->second->getAttr()->value.oid)
            {
                bridge_port_list.push_back(bp.first);
            }
        }
    }

    if (bridge_port_list_on_bridge_id.size() != bridge_port_list.size())
    {
        SWSS_LOG_THROW("filter by port id failed size on lists is different: %zu vs %zu",
                bridge_port_list_on_bridge_id.size(),
                bridge_port_list.size());
    }

    uint32_t bridge_port_list_count = (uint32_t)bridge_port_list.size();

    SWSS_LOG_NOTICE("recalculated %s: %u", m_port_list->attridname, bridge_port_list_count);

    attr.id = SAI_BRIDGE_ATTR_PORT_LIST;
    attr.value.objlist.count = bridge_port_list_count;
    attr.value.objlist.list = bridge_port_list.data();

    return vs_generic_set(SAI_OBJECT_TYPE_BRIDGE, bridge_id, &attr);
}
コード例 #13
0
sai_status_t refresh_read_only_BCM56850(
        _In_ const sai_attr_metadata_t *meta,
        _In_ sai_object_id_t object_id,
        _In_ sai_object_id_t switch_id)
{
    SWSS_LOG_ENTER();

    if (meta->objecttype == SAI_OBJECT_TYPE_SWITCH)
    {
        switch (meta->attrid)
        {
            case SAI_SWITCH_ATTR_PORT_NUMBER:
                return SAI_STATUS_SUCCESS;

            case SAI_SWITCH_ATTR_CPU_PORT:
            case SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID:
            case SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP:
            case SAI_SWITCH_ATTR_DEFAULT_VLAN_ID:
            case SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID:
            case SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID:
                return SAI_STATUS_SUCCESS;

            case SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY:
            case SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY:
                return SAI_STATUS_SUCCESS;

            case SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS:
                return SAI_STATUS_SUCCESS;

                /*
                 * We don't need to recalculate port list, since now we assume
                 * that port list will not change.
                 */

            case SAI_SWITCH_ATTR_PORT_LIST:
                return SAI_STATUS_SUCCESS;

            case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP:
                return SAI_STATUS_SUCCESS;
        }
    }

    if (meta->objecttype == SAI_OBJECT_TYPE_PORT)
    {
        switch (meta->attrid)
        {
            case SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES:
            case SAI_PORT_ATTR_QOS_QUEUE_LIST:
                return refresh_qos_queues(meta, object_id, switch_id);

            case SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS:
            case SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST:
                return refresh_ingress_priority_group(meta, object_id, switch_id);

            case SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS:
            case SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST:
                return refresh_scheduler_groups(meta, object_id, switch_id);

                /*
                 * This status is based on hostif vEthernetX status.
                 */

            case SAI_PORT_ATTR_OPER_STATUS:
                return SAI_STATUS_SUCCESS;
        }
    }

    if (meta->objecttype == SAI_OBJECT_TYPE_SCHEDULER_GROUP)
    {
        switch (meta->attrid)
        {
            case SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT:
            case SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST:
                return refresh_scheduler_groups(meta, object_id, switch_id);
        }
    }

    if (meta->objecttype == SAI_OBJECT_TYPE_BRIDGE && meta->attrid == SAI_BRIDGE_ATTR_PORT_LIST)
    {
        return refresh_bridge_port_list(meta, object_id, switch_id);
    }

    if (meta->objecttype == SAI_OBJECT_TYPE_VLAN && meta->attrid == SAI_VLAN_ATTR_MEMBER_LIST)
    {
        return refresh_vlan_member_list(meta, object_id, switch_id);
    }

    if (meta_unittests_enabled())
    {
        SWSS_LOG_NOTICE("unittests enabled, SET could be performed on %s, not recalculating", meta->attridname);

        return SAI_STATUS_SUCCESS;
    }

    SWSS_LOG_WARN("need to recalculate RO: %s", meta->attridname);

    return SAI_STATUS_NOT_IMPLEMENTED;
}
コード例 #14
0
/**
 * Function Description:
 *    @brief adds a decap tunnel termination entry to ASIC_DB
 *
 * Arguments:
 *    @param[in] tunnelKey - key of the tunnel from APP_DB
 *    @param[in] dst_ip - destination ip addresses to decap
 *    @param[in] tunnel_id - the id of the tunnel
 *
 * Return Values:
 *    @return true on success and false if there's an error
 */
bool TunnelDecapOrch::addDecapTunnelTermEntries(string tunnelKey, IpAddresses dst_ip, sai_object_id_t tunnel_id)
{
    SWSS_LOG_ENTER();

    sai_attribute_t attr;

    // adding tunnel table entry attributes to array and writing to ASIC_DB
    vector<sai_attribute_t> tunnel_table_entry_attrs;
    attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID;
    attr.value.oid = gVirtualRouterId;
    tunnel_table_entry_attrs.push_back(attr);

    attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE;
    attr.value.u32 = SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP;
    tunnel_table_entry_attrs.push_back(attr);

    attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE;
    attr.value.s32 = SAI_TUNNEL_TYPE_IPINIP;
    tunnel_table_entry_attrs.push_back(attr);

    attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID;
    attr.value.oid = tunnel_id;
    tunnel_table_entry_attrs.push_back(attr);

    TunnelEntry *tunnel_info = &tunnelTable.find(tunnelKey)->second;

    // loop through the IP list and create a new tunnel table entry for every IP (in network byte order)
    set<IpAddress> tunnel_ips = dst_ip.getIpAddresses();
    for (auto it = tunnel_ips.begin(); it != tunnel_ips.end(); ++it)
    {
        const IpAddress& ia = *it;
        string ip = ia.to_string();

        // check if the there's an entry already for the ip
        if (existingIps.find(ip) != existingIps.end())
        {
            SWSS_LOG_ERROR("%s already exists. Did not create entry.", ip.c_str());
        }
        else
        {
            attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP;
            copy(attr.value.ipaddr, ia);
            tunnel_table_entry_attrs.push_back(attr);

            // create the tunnel table entry
            sai_object_id_t tunnel_term_table_entry_id;
            sai_status_t status = sai_tunnel_api->create_tunnel_term_table_entry(&tunnel_term_table_entry_id, gSwitchId, (uint32_t)tunnel_table_entry_attrs.size(), tunnel_table_entry_attrs.data());
            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("Failed to create tunnel entry table for ip: %s", ip.c_str());
                return false;
            }

            // insert into ip to entry mapping
            existingIps.insert(ip);

            // insert entry id and ip into tunnel mapping
            tunnel_info->tunnel_term_info.push_back({ tunnel_term_table_entry_id, ip });

            // pop the last element for the next loop
            tunnel_table_entry_attrs.pop_back();

            SWSS_LOG_NOTICE("Created tunnel entry for ip: %s", ip.c_str());
        }

    }
    return true;
}
コード例 #15
0
/*
 * Before stopping orchagent for warm restart, basic state check is preferred to
 * ensure orchagent is not in transient state, so a deterministic state may be restored after restart.
 *
 * Here is to implement orchagent_restart_check binary which may talk to orchagent and
 * ask it to do self-check, return "READY " signal and freeze if everything is ok,
 * otherwise "NOT_READY" signal should be returned.
 *
 * Optionally:
 *            if --noFreeze option is provided, orchagent won't freeze.
 *            if --skipPendingTaskCheck option is provided, orchagent won't use
 *                 whether there is pending task existing as state check criterion.
 */
int main(int argc, char **argv)
{
    swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_INFO);
    SWSS_LOG_ENTER();

    std::string skipPendingTaskCheck = "fasle";
    std::string noFreeze            = "fasle";
    /* Default wait time is 1000 millisecond */
    int waitTime = 1000;

    const char* const optstring = "nsw:";
    while(true)
    {
        static struct option long_options[] =
        {
            { "noFreeze",                no_argument,       0, 'n' },
            { "skipPendingTaskCheck",    no_argument,       0, 's' },
            { "waitTime",                required_argument, 0, 'w' }
        };

        int option_index = 0;

        int c = getopt_long(argc, argv, optstring, long_options, &option_index);

        if (c == -1)
        {
            break;
        }

        switch (c)
        {
            case 'n':
                SWSS_LOG_NOTICE("Won't freeze orchagent even if check succeeded");
                noFreeze = "true";
                break;
            case 's':
                SWSS_LOG_NOTICE("Skipping pending task check for orchagent");
                skipPendingTaskCheck = "true";
                break;
            case 'w':
                SWSS_LOG_NOTICE("Wait time for response from orchagent set to %s milliseconds", optarg);
                waitTime = atoi(optarg);
                break;
            case 'h':
                printUsage();
                exit(EXIT_SUCCESS);

            case '?':
                SWSS_LOG_WARN("unknown option %c", optopt);
                printUsage();
                exit(EXIT_FAILURE);

            default:
                SWSS_LOG_ERROR("getopt_long failure");
                exit(EXIT_FAILURE);
        }
    }

    swss::DBConnector db(APPL_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0);
    // Send warm restart query via "RESTARTCHECK" notification channel
    swss::NotificationProducer restartQuery(&db, "RESTARTCHECK");
    // Will listen for the reply on "RESTARTCHECKREPLY" channel
    swss::NotificationConsumer restartQueryReply(&db, "RESTARTCHECKREPLY");

    std::vector<swss::FieldValueTuple> values;
    values.emplace_back("NoFreeze", noFreeze);
    values.emplace_back("SkipPendingTaskCheck", skipPendingTaskCheck);
    std::string op = "orchagent";
    SWSS_LOG_NOTICE("requested %s to do warm restart state check", op.c_str());
    restartQuery.send(op, op, values);


    swss::Select s;
    s.addSelectable(&restartQueryReply);
    swss::Selectable *sel;
    std::string op_ret, data;
    values.clear();
    int result = s.select(&sel, waitTime);
    if (result == swss::Select::OBJECT)
    {
        restartQueryReply.pop(op_ret, data, values);
        if (data == "READY")
        {
            SWSS_LOG_NOTICE("RESTARTCHECK success, %s is frozen and ready for warm restart", op_ret.c_str());
            std::cout << "RESTARTCHECK succeeded" << std::endl;
            return EXIT_SUCCESS;
        }
        else
        {
            SWSS_LOG_NOTICE("RESTARTCHECK failed, %s is not ready for warm restart with status %s",
                    op_ret.c_str(), data.c_str());
        }
    }
    else if (result == swss::Select::TIMEOUT)
    {
        SWSS_LOG_NOTICE("RESTARTCHECK for %s timed out", op_ret.c_str());
    }
    else
    {
        SWSS_LOG_NOTICE("RESTARTCHECK for %s error", op_ret.c_str());
    }
    std::cout << "RESTARTCHECK failed" << std::endl;
    return EXIT_FAILURE;
}
コード例 #16
0
ファイル: syncd_cli.cpp プロジェクト: kcudnik/sonic-sairedis
void cli_thread_function()
{
    SWSS_LOG_ENTER();

    cli_server_socket = socket(AF_INET, SOCK_STREAM, 0);

    if (cli_server_socket < 0)
    {
        SWSS_LOG_ERROR("open socket failed, errno: %s", strerror(errno));
        return;
    }

    struct sockaddr_in serv_addr;

    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(CLI_PORT);

    if (bind(cli_server_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != 0)
    {
        SWSS_LOG_ERROR("bind socket failed, errno: %s", strerror(errno));
        close(cli_server_socket);
        return;
    }

    const int backlog = 5;

    if (listen(cli_server_socket, backlog) != 0)
    {
        SWSS_LOG_ERROR("listen on socket failed, errno: %s", strerror(errno));
        close(cli_server_socket);
        return;
    }

    while (run_cli)
    {
        struct sockaddr_in cli_addr;

        memset(&cli_addr, 0, sizeof(cli_addr));

        socklen_t clilen = sizeof(cli_addr);

        SWSS_LOG_NOTICE("accepting connections for cli");

        cli_client_socket = accept(cli_server_socket, (struct sockaddr *) &cli_addr, &clilen);

        if (cli_client_socket < 0)
        {
            // don't log when run is false, that's mean we closed socket
            if (run_cli)
            {
                SWSS_LOG_ERROR("accept failed, errno: %s", strerror(errno));
            }

            break;
        }

        SWSS_LOG_NOTICE("client connected to cli");

        // we allow only 1 connection at given time
        handle_cli();

        close(cli_client_socket);
    }

    close(cli_server_socket);
}
コード例 #17
0
int main(int argc, char **argv)
{
    swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);

    SWSS_LOG_ENTER();

    auto options = handleCmdLine(argc, argv);

    handleProfileMap(options.profileMapFile);
#ifdef SAITHRIFT
    if (options.portMapFile.size() > 0)
    {
        handlePortMap(options.portMapFile);
    }
#endif // SAITHRIFT

    swss::DBConnector *db = new swss::DBConnector(ASIC_DB, "localhost", 6379, 0);
    swss::DBConnector *dbNtf = new swss::DBConnector(ASIC_DB, "localhost", 6379, 0);

    g_redisClient = new swss::RedisClient(db);

    updateLogLevel();

    swss::ConsumerTable *asicState = new swss::ConsumerTable(db, "ASIC_STATE");
    swss::NotificationConsumer *notifySyncdQuery = new swss::NotificationConsumer(db, "NOTIFYSYNCDREQUERY");
    swss::NotificationConsumer *restartQuery = new swss::NotificationConsumer(db, "RESTARTQUERY");

    // at the end we cant use producer consumer concept since
    // if one proces will restart there may be something in the queue
    // also "remove" from response queue will also trigger another "response"
    getRequest = new swss::ConsumerTable(db, "GETREQUEST");
    getResponse  = new swss::ProducerTable(db, "GETRESPONSE");
    notifications = new swss::NotificationProducer(dbNtf, "NOTIFICATIONS");
    notifySyncdResponse = new swss::NotificationProducer(db, "NOTIFYSYNCDRESPONSE");

    g_veryFirstRun = isVeryFirstRun();

    if (options.startType == SAI_WARM_BOOT)
    {
        const char *warmBootReadFile = profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE);

        SWSS_LOG_NOTICE("using warmBootReadFile: '%s'", warmBootReadFile);

        if (warmBootReadFile == NULL || access(warmBootReadFile, F_OK) == -1)
        {
            SWSS_LOG_WARN("user requested warmStart but warmBootReadFile is not specified or not accesible, forcing cold start");

            options.startType = SAI_COLD_BOOT;
        }
    }

    if (options.startType == SAI_WARM_BOOT && g_veryFirstRun)
    {
        SWSS_LOG_WARN("warm start requested, but this is very first syncd start, forcing cold start");

        // we force cold start since if it's first run then redis db is not complete
        // so redis asic view will not reflect warm boot asic state, if this happen
        // then orch agent needs to be restarted as well to repopulate asic view
        options.startType = SAI_COLD_BOOT;
    }

    gProfileMap[SAI_KEY_BOOT_TYPE] = std::to_string(options.startType);

    sai_api_initialize(0, (service_method_table_t*)&test_services);

    populate_sai_apis();

    initialize_common_api_pointers();

    sai_status_t status = sai_switch_api->initialize_switch(0, "", "", &switch_notifications);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("fail to sai_initialize_switch: %d", status);
        exit(EXIT_FAILURE);
    }

#ifdef BRCMSAI

    if (options.diagShell)
    {
        SWSS_LOG_NOTICE("starting bcm diag shell thread");

        std::thread bcm_diag_shell_thread = std::thread(sai_diag_shell);
        bcm_diag_shell_thread.detach();
    }

#endif /* BRCMSAI */

#ifdef SAITHRIFT
    if (options.run_rpc_server)
    {
        start_sai_thrift_rpc_server(SWITCH_SAI_THRIFT_RPC_SERVER_PORT);
        SWSS_LOG_NOTICE("rpcserver started");
    }
#endif // SAITHRIFT

    SWSS_LOG_NOTICE("syncd started");

    bool warmRestartHint = false;

    try
    {
        onSyncdStart(options.startType == SAI_WARM_BOOT);

        if (options.disableCountersThread == false)
        {
            SWSS_LOG_NOTICE("starting counters thread");

            startCountersThread(options.countersThreadIntervalInSeconds);
        }

        SWSS_LOG_NOTICE("syncd listening for events");

        swss::Select s;

        s.addSelectable(getRequest);
        s.addSelectable(asicState);
        s.addSelectable(notifySyncdQuery);
        s.addSelectable(restartQuery);

        while(true)
        {
            swss::Selectable *sel;

            int fd;

            int result = s.select(&sel, &fd);

            if (sel == restartQuery)
            {
                warmRestartHint = handleRestartQuery(*restartQuery);
                break;
            }

            if (sel == notifySyncdQuery)
            {
                notifySyncd(*notifySyncdQuery);
                continue;
            }

            if (result == swss::Select::OBJECT)
            {
                processEvent(*(swss::ConsumerTable*)sel);
            }
        }
    }
    catch(const std::exception &e)
    {
        SWSS_LOG_ERROR("Runtime error: %s", e.what());

        exit(EXIT_FAILURE);
    }

    endCountersThread();

    if (warmRestartHint)
    {
        const char *warmBootWriteFile = profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE);

        SWSS_LOG_NOTICE("using warmBootWriteFile: '%s'", warmBootWriteFile);

        if (warmBootWriteFile == NULL)
        {
            SWSS_LOG_WARN("user requested warm shutdown but warmBootWriteFile is not specified, forcing cold shutdown");

            warmRestartHint = false;
        }
    }

    sai_switch_api->shutdown_switch(warmRestartHint);

    SWSS_LOG_NOTICE("calling api uninitialize");

    sai_api_uninitialize();

    SWSS_LOG_NOTICE("uninitialize finished");

    return EXIT_SUCCESS;
}