sai_status_t Syncd::processNotifySyncd()

in syncd/Syncd.cpp [4169:4373]


sai_status_t Syncd::processNotifySyncd(
        _In_ const swss::KeyOpFieldsValuesTuple &kco)
{
    SWSS_LOG_ENTER();

    auto& key = kfvKey(kco);
    sai_status_t status = SAI_STATUS_SUCCESS;
    auto redisNotifySyncd = sai_deserialize_redis_notify_syncd(key);

    if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_INVOKE_DUMP)
    {
        SWSS_LOG_NOTICE("Invoking SAI failure dump");
        std::string ret_str;
        int ret = swss::exec(SAI_FAILURE_DUMP_SCRIPT, ret_str);
        if (ret != 0)
        {
            SWSS_LOG_ERROR("Error in executing SAI failure dump %s", ret_str.c_str());
            status = SAI_STATUS_FAILURE;
        }
        sendNotifyResponse(status);
        return status;
    }

    if (!m_commandLineOptions->m_enableTempView)
    {
        SWSS_LOG_NOTICE("received %s, ignored since TEMP VIEW is not used, returning success", key.c_str());

        sendNotifyResponse(SAI_STATUS_SUCCESS);

        return SAI_STATUS_SUCCESS;
    }

    if (m_veryFirstRun && m_firstInitWasPerformed && redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW)
    {
        /*
         * Make sure that when second INIT view arrives, then we will jump to
         * next section, since second init view may create switch that already
         * exists and will fail with creating multiple switches error.
         */

        m_veryFirstRun = false;
    }
    else if (m_veryFirstRun)
    {
        SWSS_LOG_NOTICE("very first run is TRUE, op = %s", key.c_str());


        /*
         * On the very first start of syncd, "compile" view is directly applied
         * on device, since it will make it easier to switch to new asic state
         * later on when we restart orch agent.
         */

        if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW)
        {
            /*
             * On first start we just do "apply" directly on asic so we set
             * init to false instead of true.
             */

            m_asicInitViewMode = false;

            m_firstInitWasPerformed = true;

            // we need to clear current temp view to make space for new one

            clearTempView();
        }
        else if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_APPLY_VIEW)
        {
            m_veryFirstRun = false;

            m_asicInitViewMode = false;
#ifdef MELLANOX
            bool applyViewInFastFastBoot = m_commandLineOptions->m_startType == SAI_START_TYPE_FASTFAST_BOOT ||
                                           m_commandLineOptions->m_startType == SAI_START_TYPE_EXPRESS_BOOT ||
                                           m_commandLineOptions->m_startType == SAI_START_TYPE_FAST_BOOT;
#else
            bool applyViewInFastFastBoot = m_commandLineOptions->m_startType == SAI_START_TYPE_FASTFAST_BOOT ||
                                           m_commandLineOptions->m_startType == SAI_START_TYPE_EXPRESS_BOOT;
#endif
            if (applyViewInFastFastBoot)
            {
                // express/fastfast boot configuration end

                status = onApplyViewInFastFastBoot();
            }

            SWSS_LOG_NOTICE("setting very first run to FALSE, op = %s", key.c_str());
        }
        else if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_INSPECT_ASIC)
        {
            SWSS_LOG_NOTICE("syncd switched to INSPECT ASIC mode");

            inspectAsic();

            sendNotifyResponse(SAI_STATUS_SUCCESS);
        }
        else
        {
            SWSS_LOG_THROW("unknown operation: %s", key.c_str());
        }

        sendNotifyResponse(status);

        return status;
    }

    if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW)
    {
        if (m_asicInitViewMode)
        {
            SWSS_LOG_WARN("syncd is already in asic INIT VIEW mode, but received init again, orchagent restarted before apply?");
        }

        m_asicInitViewMode = true;

        clearTempView();

        m_createdInInitView.clear();

        // NOTE: Currently as WARN to be easier to spot, later should be NOTICE.

        SWSS_LOG_WARN("syncd switched to INIT VIEW mode, all op will be saved to TEMP view");

        sendNotifyResponse(SAI_STATUS_SUCCESS);
    }
    else if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_APPLY_VIEW)
    {
        m_asicInitViewMode = false;

        // NOTE: Currently as WARN to be easier to spot, later should be NOTICE.

        SWSS_LOG_WARN("syncd received APPLY VIEW, will translate");


        try
        {
            status = applyView();
        }
        catch(...)
        {
            /*
             * If apply view will fail with exception, try to send fail
             * response to sairedis, since later there can be switch shutdown
             * notification sent, and it will be synchronized with mutex, and
             * it will not be processed until get response timeout will hit.
             */

            sendNotifyResponse(SAI_STATUS_FAILURE);

            throw;
        }

        sendNotifyResponse(status);

        if (status == SAI_STATUS_SUCCESS)
        {
            /*
             * We successfully applied new view, VID mapping could change, so
             * we need to clear local db, and all new VIDs will be queried
             * using redis.
             *
             * TODO possible race condition - get notification when new view is
             * applied and cache have old values, and notification start's
             * translating vid/rid, we need to stop processing notifications
             * for transition (queue can still grow), possible fdb
             * notifications but fdb learning was disabled on warm boot, so
             * there should be no issue.
             */

            m_translator->clearLocalCache();

            m_createdInInitView.clear();
        }
        else
        {
            /*
             * Apply view failed. It can fail in 2 ways, ether nothing was
             * executed, on asic, or asic is inconsistent state then we should
             * die or hang.
             */

            return status;
        }
    }
    else if (redisNotifySyncd == SAI_REDIS_NOTIFY_SYNCD_INSPECT_ASIC)
    {
        SWSS_LOG_NOTICE("syncd switched to INSPECT ASIC mode");

        inspectAsic();

        sendNotifyResponse(SAI_STATUS_SUCCESS);
    }
    else
    {
        SWSS_LOG_ERROR("unknown operation: %s", key.c_str());

        sendNotifyResponse(SAI_STATUS_NOT_IMPLEMENTED);

        SWSS_LOG_THROW("notify syncd %s operation failed", key.c_str());
    }

    return SAI_STATUS_SUCCESS;
}