/*
<:copyright-BRCM:2016:DUAL/GPL:standard

   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
   All Rights Reserved

Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:

   As a special exception, the copyright holders of this software give
   you permission to link this software with independent modules, and
   to copy and distribute the resulting executable under terms of your
   choice, provided that you also meet, for each linked independent
   module, the terms and conditions of the license of that module.
   An independent module is a module which is not derived from this
   software.  The special exception does not apply to any modifications
   of the software.

Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.

:>
*/

/* This file contains the pieces of the OAM negotiation state machine that are specific to CTC OAM. */

#include "bcmolt_eon_private.h"
#include "../oam_common.h"
#include "ctc.h"

#define CTC_EXTENSION_SUPPORT 0x1
#define CTC_PREFERRED_VERSION 0x30

typedef enum
{
    CTC_NEG_ADVERTISING,
    CTC_NEG_CONFIRMING,
    CTC_NEG_DONE
} ctc_neg_state;

typedef struct
{
    ctc_neg_state state;
    uint8_t selected_version;
} ctc_state;

static bcmolt_epon_oam_ctc_oui_version_pair ctc_advertised_versions[] =
{
    { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x30 },
    { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x21 },
    { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x20 },
    { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x13 },
    { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x01 }
};

/* Org specific TLV to send to the ONU */
static const bcmolt_epon_oam_organization_specific_info ctc_tx_advertise_tlv =
{
    .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC,
    .u =
    {
        .ctc =
        {
            .extension_support = CTC_EXTENSION_SUPPORT,
            .version = CTC_PREFERRED_VERSION,
            .supp_version_count = NUM_ELEM(ctc_advertised_versions),
            .supp_version = ctc_advertised_versions
        }
    }
};

void ctc_tx_add_tlv(eon_link_state *link_state, bcmolt_epon_oam_oam_pdu_content *oam)
{
    ctc_state *ctc = link_state->org_spec_state;

    if (ctc != NULL)
    {
        switch (ctc->state)
        {
            case CTC_NEG_ADVERTISING:
                oam->u.info.tlvs[oam->u.info.tlvs_count].type = BCMOLT_EPON_OAM_INFO_TLV_TYPE_ORGANIZATION_SPECIFIC;
                oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value = ctc_tx_advertise_tlv;
                oam->u.info.tlvs_count++;
                break;
            case CTC_NEG_CONFIRMING:
                oam->u.info.tlvs[oam->u.info.tlvs_count].type = BCMOLT_EPON_OAM_INFO_TLV_TYPE_ORGANIZATION_SPECIFIC;
                oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.oui =
                    BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC;
                oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.extension_support =
                    CTC_EXTENSION_SUPPORT;
                oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.version =
                    ctc->selected_version;
                oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.supp_version_count = 0;
                oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.supp_version = NULL;
                oam->u.info.tlvs_count++;
                break;
            case CTC_NEG_DONE:
                break; /* don't add a TLV */
            default:
                EON_LINK_LOG(ERROR, &link_state->link_key, "Unknown CTC state %d\n", ctc->state);
                break;
        }
    }
}

void ctc_rx_tlv(
    eon_link_state *link_state,
    bcmolt_epon_oam_organization_specific_info *org_spec,
    bcmos_errno *rc)
{
    *rc = BCM_ERR_IN_PROGRESS;

    if (link_state->org_spec_state != NULL)
    {
        ctc_state *ctc = link_state->org_spec_state;

        switch (ctc->state)
        {
            case CTC_NEG_ADVERTISING:
                if ((NULL == org_spec) || (BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC != org_spec->oui))
                {
                    EON_LINK_LOG(INFO, &link_state->link_key, "Didn't get CTC advertise TLV\n");
                    *rc = BCM_ERR_ONU_ERR_RESP;
                }
                else
                {
                    /* find highest common version */
                    ctc->selected_version = 0;
                    for (uint8_t i = 0; i < org_spec->u.ctc.supp_version_count; i++)
                    {
                        for (uint8_t j = 0; j < NUM_ELEM(ctc_advertised_versions); j++)
                        {
                            if ((org_spec->u.ctc.supp_version[i].oui == ctc_advertised_versions[j].oui) &&
                                (org_spec->u.ctc.supp_version[i].version == ctc_advertised_versions[j].version))
                            {
                                if (ctc_advertised_versions[j].version > ctc->selected_version)
                                {
                                    ctc->selected_version = ctc_advertised_versions[j].version;
                                }
                            }
                        }
                    }
                    if (ctc->selected_version == 0)
                    {
                        *rc = BCM_ERR_NOT_SUPPORTED; /* no common version found */
                    }
                    else
                    {
                        ctc->state = CTC_NEG_CONFIRMING;
                    }
                }
                break;
            case CTC_NEG_CONFIRMING:
                if ((NULL == org_spec) || (BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC != org_spec->oui))
                {
                    EON_LINK_LOG(INFO, &link_state->link_key, "Didn't get CTC confirm TLV\n");
                    *rc = BCM_ERR_ONU_ERR_RESP;
                }
                else
                {
                    if (org_spec->u.ctc.supp_version_count == 0)
                    {
                        if (org_spec->u.ctc.version != ctc->selected_version)
                        {
                            *rc = BCM_ERR_NOT_SUPPORTED;
                        }
                        else
                        {
                            ctc->state = CTC_NEG_DONE;
                        }
                    }
                }
                break;
            case CTC_NEG_DONE:
                if ((NULL != org_spec) && (org_spec->oui == BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC))
                {
                    EON_LINK_LOG(
                        INFO, &link_state->link_key, "Got unexpected CTC TLV after negotiation\n");
                    *rc = BCM_ERR_ONU_ERR_RESP;
                }
                else
                {
                    *rc = BCM_ERR_OK;
                }
                break;
            default:
                break;
        }
    }
    else
    {
        if ((NULL != org_spec) && (org_spec->oui == BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC))
        {
            EON_LINK_LOG(
                INFO, &link_state->link_key, "Got unexpected CTC TLV before negotiation\n");
            *rc = BCM_ERR_ONU_ERR_RESP;
        }

        if (LOCAL_STABLE_REMOTE_STABLE == link_state->oam_state)
        {
            ctc_state *ctc = bcmos_calloc(sizeof(ctc_state));
            ctc->state = CTC_NEG_ADVERTISING;
            link_state->org_spec_state = ctc;
        }
    }
}

