/*
 <: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.

 :>
 */

#include <bcmos_system.h>
#include <bcmolt_api.h>
#include <bcmolt_model_types.h>
#include <bcmcli_session.h>
#include <bcmolt_msg_pack.h>
#include <bcm_dev_log.h>
#include <encrypt_oam.h>
#include <oam_defs.h>
#include "bcmolt_epon_hde.h"

#define HDE_TASK_MSG_Q_SIZE 64
#define ENC_KEY_LENGTH_KEY 16
#define HDE_MAX_NUM_LINKS 512
#define KEY_EXCHANGE_PERIOD 15

typedef enum
{
    HDE_EVENT_ENABLE_ENCRYPTION,
    HDE_EVENT_DISABLE_ENCRYPTION,
    HDE_EVENT_FRAME_RX,
    HDE_EVENT_OAM_TIMEOUT,
    HDE_EVENT__NUM_OF
} hde_event;

typedef enum
{
    HDE_STATE_NOT_ENCRYPTED,
    HDE_STATE_ENCRYPTED,
    HDE_STATE_WAITING_FOR_OAM_ACK,
    HDE_STATE__NUM_OF
} hde_state;

typedef struct
{
    bcmos_msg os_msg;
    bcmolt_msg *rx;
    hde_key key;
    hde_event event;
} hde_task_msg;

typedef struct
{
    hde_key hde_link;
    hde_state state;
    bcmos_timer oam_timeout_timer;
    bcmolt_epon_link_rate link_rate;
    bcmolt_epon_llid llid;
    bcmos_mac_address corresponding_pon_port_mac;
} hde_link_data;

static struct
{
    bcmos_task task;
    dev_log_id log_id[BCMTR_MAX_OLTS];
    hde_link_data *links;
    uint16_t num_links;
} hde_data;

static bcmos_bool is_running = BCMOS_FALSE;

typedef void (*link_state_handler)(hde_link_data *hde_link, const bcmolt_msg *ind);

static const char *get_state_string(hde_state state)
{
    switch (state)
    {
    case HDE_STATE_NOT_ENCRYPTED:
        return "not encrypted";
    case HDE_STATE_ENCRYPTED:
        return "encrypted";
    case HDE_STATE_WAITING_FOR_OAM_ACK:
        return "waiting for oam ack";
    default:
        return "UNKNOWN STATE!!!";
    }
}

static bcmos_errno set_new_key(const hde_key *hde_link, bcmolt_encryption_information_container *new_key, bcmolt_epon_key_choice key_choice, bcmolt_epon_encryption_mode mode)
{
    bcmolt_epon_link_cfg link_cfg;
    bcmolt_epon_encryption_config encryption_config = { };

    // Up/down format must match even when doing DS only
    encryption_config.upstream_encryption_information.format = new_key->format;

    encryption_config.downstream_encryption_information = *new_key;
    encryption_config.downstream_key_choice = key_choice;
    encryption_config.downstream_mode = mode;
    bcmolt_epon_link_key link_key =
    {
        .epon_ni = hde_link->epon_ni,
        .mac_address = hde_link->mac_addr
    };
    BCMOLT_CFG_INIT(&link_cfg, epon_link, link_key);
    BCMOLT_CFG_PROP_SET(&link_cfg, epon_link, epon_encryption, encryption_config);
    return bcmolt_cfg_set(hde_link->device_id, &link_cfg.hdr);
}

static bcmos_errno set_pon_encryption_if_needed(const hde_key *hde_link)
{
    // First check the current state of the PON's encryption mode.
    bcmos_errno rc;
    bcmolt_epon_ni_cfg pon_cfg;
    bcmolt_epon_ni_key pon_key = { .epon_ni = hde_link->epon_ni };
    BCMOLT_CFG_INIT(&pon_cfg, epon_ni, pon_key);
    BCMOLT_CFG_PROP_GET(&pon_cfg, epon_ni, encryption_cfg);
    rc = bcmolt_cfg_get(hde_link->device_id, &pon_cfg.hdr);
    if (rc != BCM_ERR_OK)
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->device_id], "Failure - Cannot query PON encryption mode!.\n");
        return rc;
    }

    if (pon_cfg.data.encryption_cfg.downstream_encryption_mode != BCMOLT_EPON_ENCRYPTION_MODE_EPON_ZERO_OVERHEAD_AES)
    {
        // Encryption mode is not correctly set on the PON, so set it now.
        pon_cfg.data.encryption_cfg.downstream_encryption_mode = BCMOLT_EPON_ENCRYPTION_MODE_EPON_ZERO_OVERHEAD_AES;
        pon_cfg.data.encryption_cfg.upstream_encryption_mode = BCMOLT_EPON_ENCRYPTION_MODE_NO_ENCRYPTION;
        rc = bcmolt_cfg_set(hde_link->device_id, &pon_cfg.hdr);
        if (rc != BCM_ERR_OK)
        {
            BCM_LOG(ERROR, hde_data.log_id[hde_link->device_id], "Failure - Cannot set PON encryption mode!.\n");
            return rc;
        }
    }

    return BCM_ERR_OK;
}

static bcmolt_epon_link_rate get_link_rate(const hde_key *hde_link)
{
    bcmos_errno rc;
    bcmolt_epon_link_cfg link_cfg;
    bcmolt_epon_link_key link_key =
    {
        .epon_ni = hde_link->epon_ni,
        .mac_address = hde_link->mac_addr
    };
    BCMOLT_CFG_INIT(&link_cfg, epon_link, link_key);
    BCMOLT_CFG_PROP_GET(&link_cfg, epon_link, link_rate);
    rc = bcmolt_cfg_get(hde_link->device_id, &link_cfg.hdr);
    if (rc != BCM_ERR_OK)
    {
        BCM_LOG(
            ERROR,
            hde_data.log_id[hde_link->device_id],
            "Failure - cannot query link rate for link %02x:%02x:%02x:%02x:%02x:%02x!.\n",
            hde_link->mac_addr.u8[0],
            hde_link->mac_addr.u8[1],
            hde_link->mac_addr.u8[2],
            hde_link->mac_addr.u8[3],
            hde_link->mac_addr.u8[4],
            hde_link->mac_addr.u8[5]);
    }
    return link_cfg.data.link_rate;
}

static bcmos_mac_address get_pon_mac(const hde_key *hde_link)
{
    bcmos_errno rc;
    bcmolt_epon_ni_cfg pon_cfg;
    bcmolt_epon_ni_key pon_key = { .epon_ni = hde_link->epon_ni };
    BCMOLT_CFG_INIT(&pon_cfg, epon_ni, pon_key);
    BCMOLT_CFG_PROP_GET(&pon_cfg, epon_ni, mac_address);
    rc = bcmolt_cfg_get(hde_link->device_id, &pon_cfg.hdr);
    if (rc != BCM_ERR_OK)
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->device_id], "Failure - Cannot query PON mac address!.\n");
    }
    return pon_cfg.data.mac_address;
}

static bcmolt_epon_llid get_llid(const hde_key *hde_link)
{
    bcmos_errno rc;
    bcmolt_epon_link_cfg link_cfg;
    bcmolt_epon_link_key link_key =
    {
        .epon_ni = hde_link->epon_ni,
        .mac_address = hde_link->mac_addr
    };
    BCMOLT_CFG_INIT(&link_cfg, epon_link, link_key);
    BCMOLT_CFG_PROP_GET(&link_cfg, epon_link, llid);
    rc = bcmolt_cfg_get(hde_link->device_id, &link_cfg.hdr);
    if (rc != BCM_ERR_OK)
    {
        BCM_LOG(
            ERROR,
            hde_data.log_id[hde_link->device_id],
            "Failure - cannot query LLID for link %02x:%02x:%02x:%02x:%02x:%02x!.\n",
            hde_link->mac_addr.u8[0],
            hde_link->mac_addr.u8[1],
            hde_link->mac_addr.u8[2],
            hde_link->mac_addr.u8[3],
            hde_link->mac_addr.u8[4],
            hde_link->mac_addr.u8[5]);
    }
    return link_cfg.data.llid;
}

/* By spec the SCI is the LLID of the link appended to the corresponding epon port mac address */
static void create_sci(const bcmos_mac_address *epon_port_mac, bcmolt_epon_llid llid, uint8_t *sci)
{
    sci[7] = (uint8_t) llid;
    sci[6] = (uint8_t) (llid >> 8);
    sci[5] = epon_port_mac->u8[5];
    sci[4] = epon_port_mac->u8[4];
    sci[3] = epon_port_mac->u8[3];
    sci[2] = epon_port_mac->u8[2];
    sci[1] = epon_port_mac->u8[1];
    sci[0] = epon_port_mac->u8[0];
}

static void handle_not_encrypted_enable_encryption(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    dpoe_encrypt_mode mode = DPOE_ENCRYPT_MODE_NONE;
    // Retreive useful link info and store it to save messages later.
    hde_link->link_rate = get_link_rate(&hde_link->hde_link);
    hde_link->corresponding_pon_port_mac = get_pon_mac(&hde_link->hde_link);
    hde_link->llid = get_llid(&hde_link->hde_link);

    if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_TEN || hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_ONE)
    {
        mode = DPOE_ENCRYPT_MODE_10DOWN;
    }
    else if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_ONE_ONE)
    {
        mode = DPOE_ENCRYPT_MODE_1DOWN;
    }
    else
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Failure - UNKNOWN LINK RATE!!!.\n");
    }

    dpoe_encrypt_oam_set_request_send(
        &hde_link->hde_link,
        KEY_EXCHANGE_PERIOD,
        mode,
        hde_link->corresponding_pon_port_mac);

    bcmos_timer_start(&hde_link->oam_timeout_timer, HDE_ENABLE_OAM_WAIT_US + OAM_TIMEOUT_GRACE_PERIOD_US);

    hde_link->state = HDE_STATE_WAITING_FOR_OAM_ACK;
}

static void handle_encrypted_disable_encryption(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    bcmolt_encryption_information_container empty_key = { };
    bcmos_errno rc;

    // Turn off encryption on the embedded side.
    rc = set_new_key(&hde_link->hde_link, &empty_key, BCMOLT_EPON_KEY_CHOICE_KEY_0, BCMOLT_EPON_ENCRYPTION_MODE_NO_ENCRYPTION);
    if (rc != BCM_ERR_OK)
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id],
            "Failure - Cannot communicate with the embedded!.\n");
    }

    // Send the disable OAM to the link. Don't bother waiting for a response.
    dpoe_encrypt_oam_set_request_send(&hde_link->hde_link, 0, DPOE_ENCRYPT_MODE_NONE, get_pon_mac(&hde_link->hde_link));

    hde_link->state = HDE_STATE_NOT_ENCRYPTED;
}

static void handle_encrypted_frame_rx(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    const bcmolt_epon_link_frame_captured *frame_captured = (const bcmolt_epon_link_frame_captured*) ind;
    uint8_t new_key[16];
    bcmolt_epon_key_choice key_choice;
    bcmos_errno rc;
    bcmolt_encryption_information_container key_for_embedded;
    rc = dpoe_encrypt_oam_parse_new_key(&frame_captured->data.frame, new_key, &key_choice);
    if (rc != BCM_ERR_OK)
    {
        // Not a DPoE new key, ignore it
        return;
    }

    if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_TEN || hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_ONE)
    {
        uint8_t sci[8];
        create_sci(&hde_link->corresponding_pon_port_mac, hde_link->llid, sci);
        key_for_embedded.format = BCMOLT_EPON_ENCRYPTION_INFORMATION_FORMAT_CTR;
        memcpy(key_for_embedded.u.ctr.key, new_key, sizeof(new_key));
        memcpy(key_for_embedded.u.ctr.sci, sci, sizeof(sci));
    }
    else if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_ONE_ONE)
    {
        key_for_embedded.format = BCMOLT_EPON_ENCRYPTION_INFORMATION_FORMAT_CFB;
        memcpy(key_for_embedded.u.cfb.key, new_key, sizeof(new_key));
    }
    else
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Failure - UNKNOWN LINK RATE!!!.\n");
    }

    rc = set_new_key(&hde_link->hde_link, &key_for_embedded, key_choice, BCMOLT_EPON_ENCRYPTION_MODE_EPON_ZERO_OVERHEAD_AES);
    if (rc != BCM_ERR_OK)
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id],
            "Failure - Cannot communicate with the embedded!.\n");
    }
}

static void handle_waiting_for_oam_ack_oam_timeout(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Failure - No response to initial OAM.\n");
    hde_link->state = HDE_STATE_NOT_ENCRYPTED;
}

static void handle_waiting_for_oam_ack_frame_rx(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    const bcmolt_epon_link_frame_captured *frame_captured = (const bcmolt_epon_link_frame_captured*) ind;
    uint8_t encrypt_mode_response;
    uint8_t key_expiry_response;
    bcmos_errno rc;

    rc = dpoe_encrypt_oam_parse_set_response(&frame_captured->data.frame, &encrypt_mode_response, &key_expiry_response);
    if (rc != BCM_ERR_OK)
    {
        // Not a encryption set reponse, ignore it
        return;
    }

    /* 0 represents 'no error'. */
    if ((encrypt_mode_response != 0) || (key_expiry_response != 0))
    {
        BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id],
            "Failure - The link refused one of the requested TLVs.\n");
        hde_link->state = HDE_STATE_NOT_ENCRYPTED;
        return;
    }

    // We have an appropriate response, so move on normally.
    bcmos_timer_stop(&hde_link->oam_timeout_timer);
    hde_link->state = HDE_STATE_ENCRYPTED;
}

static void handle_waiting_for_oam_ack_disable_encryption(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    hde_link->state = HDE_STATE_NOT_ENCRYPTED;
}

static void handle_ignore(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    // Literally do nothing
}

static void handle_error(hde_link_data *hde_link, const bcmolt_msg *ind)
{
    BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Unexpected event in state %s\n",
        get_state_string(hde_link->state));
}

static link_state_handler link_state_machine[HDE_STATE__NUM_OF][HDE_EVENT__NUM_OF] =
{
    [HDE_STATE_NOT_ENCRYPTED] =
    {
        [HDE_EVENT_ENABLE_ENCRYPTION] = handle_not_encrypted_enable_encryption,
        [HDE_EVENT_DISABLE_ENCRYPTION] = handle_error,
        [HDE_EVENT_FRAME_RX] = handle_ignore,
        [HDE_EVENT_OAM_TIMEOUT] = handle_ignore,
    },
    [HDE_STATE_ENCRYPTED] =
    {
        [HDE_EVENT_ENABLE_ENCRYPTION] = handle_error,
        [HDE_EVENT_DISABLE_ENCRYPTION] = handle_encrypted_disable_encryption,
        [HDE_EVENT_FRAME_RX] = handle_encrypted_frame_rx,
        [HDE_EVENT_OAM_TIMEOUT] = handle_ignore,
    },
    [HDE_STATE_WAITING_FOR_OAM_ACK] =
    {
        [HDE_EVENT_ENABLE_ENCRYPTION] = handle_error,
        [HDE_EVENT_DISABLE_ENCRYPTION] = handle_waiting_for_oam_ack_disable_encryption,
        [HDE_EVENT_FRAME_RX] = handle_waiting_for_oam_ack_frame_rx,
        [HDE_EVENT_OAM_TIMEOUT] = handle_waiting_for_oam_ack_oam_timeout,
    }
};

static int32_t find_table_index(const hde_key *hde_link)
{
    uint16_t i;
    for (i = 0; i < hde_data.num_links; ++i)
    {
        if (memcmp(hde_link, &hde_data.links[i], sizeof(*hde_link)) == 0)
        {
            return i;
        }
    }
    return -1;
}

static void remove_link_from_table(int32_t link_index)
{
    int32_t i;
    for (i = link_index; i < hde_data.num_links - 1; ++i)
    {
        /* Backwards copy all data expect for the timer handle */
        hde_data.links[i].hde_link = hde_data.links[i + 1].hde_link;
        hde_data.links[i].link_rate = hde_data.links[i + 1].link_rate;
        hde_data.links[i].llid = hde_data.links[i + 1].llid;
        hde_data.links[i].state = hde_data.links[i + 1].state;
    }
    /* also clear the state of the now empty link */
    hde_data.links[hde_data.num_links - 1].state = HDE_STATE_NOT_ENCRYPTED;
    hde_data.num_links--;
}

static void run_state_machine(int32_t link_index, const hde_task_msg *task_msg)
{
    if (link_index < 0) // We don't know of this link yet.
    {
        if (hde_data.num_links == HDE_MAX_NUM_LINKS)
        {
            BCM_LOG(ERROR, hde_data.log_id[task_msg->key.device_id], "Failure - Cannot add any more links!.\n");
            return;
        }

        link_index = hde_data.num_links;
        hde_data.links[link_index].hde_link = task_msg->key;
        link_state_machine[hde_data.links[link_index].state][task_msg->event](&hde_data.links[link_index], task_msg->rx);

        if (hde_data.links[link_index].state != HDE_STATE_NOT_ENCRYPTED)
        {
            // This link did not end in the state 'not encrypted', so we need to start tracking him.
            ++hde_data.num_links;
        }
    }
    else // We already know of this link.
    {
        link_state_machine[hde_data.links[link_index].state][task_msg->event](&hde_data.links[link_index], task_msg->rx);

        if (hde_data.links[link_index].state == HDE_STATE_NOT_ENCRYPTED)
        {
            // The link has is no longer encrypted so lets forget about him.
            remove_link_from_table(link_index);
        }
    }
}

static void hde_handle_event(bcmos_module_id module_id, bcmos_msg *os_msg)
{
    hde_task_msg *task_msg = (hde_task_msg *) os_msg;

    int32_t link_index;

    link_index = find_table_index(&task_msg->key);
    run_state_machine(link_index, task_msg);

    if (task_msg->rx != NULL)
    {
        bcmolt_msg_free(task_msg->rx);
    }
    bcmos_free(task_msg);
}

static bcmos_timer_rc oam_response_timeout(bcmos_timer *timer, long data)
{
    hde_task_msg *task_msg = bcmos_calloc(sizeof(*task_msg));

    BUG_UNLESS(task_msg);

    task_msg->key = hde_data.links[data].hde_link;
    task_msg->event = HDE_EVENT_OAM_TIMEOUT;
    task_msg->os_msg.handler = hde_handle_event;

    bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &task_msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
    return BCMOS_TIMER_OK;
}

static bcmos_errno hde_set_encryption(hde_key* key, bcmos_bool enabled)
{
    bcmos_errno rc = BCM_ERR_OK;

    hde_task_msg *task_msg = bcmos_calloc(sizeof(*task_msg));

    BUG_UNLESS(task_msg);

    task_msg->key = *key;
    task_msg->event = enabled ? HDE_EVENT_ENABLE_ENCRYPTION : HDE_EVENT_DISABLE_ENCRYPTION;
    task_msg->os_msg.handler = hde_handle_event;

    rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &task_msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
    BUG_ON(rc != BCM_ERR_OK);
    return rc;
}

static bcmos_errno hde_cli_enable(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
    bcmos_errno rc = BCM_ERR_OK;
    hde_key key =
    {
        .device_id = current_device,
        .epon_ni = (bcmolt_epon_ni)(bcmcli_find_named_parm(session, "epon_ni")->value.number),
        .mac_addr = (bcmos_mac_address)(bcmcli_find_named_parm(session, "mac_address")->value.mac)
    };

    rc = set_pon_encryption_if_needed(&key);
    if (rc != BCM_ERR_OK)
    {
        return rc;
    }
    return hde_set_encryption(&key, BCMOS_TRUE);
}

static bcmos_errno hde_cli_disable(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
    hde_key key =
    {
        .device_id = current_device,
        .epon_ni = (bcmolt_epon_ni)(bcmcli_find_named_parm(session, "epon_ni")->value.number),
        .mac_addr = (bcmos_mac_address)(bcmcli_find_named_parm(session, "mac_address")->value.mac)
    };

    return hde_set_encryption(&key, BCMOS_FALSE);
}

// public indication handler interface -- called in transport layer context
bcmos_errno bcmolt_epon_hde_process_rx(bcmolt_devid device_id, uint8_t instance, bcmolt_proxy_rx *rx)
{
    bcmos_errno rc = BCM_ERR_OK;
    bcmolt_epon_link_frame_captured* actual_rx;
    hde_task_msg *task_msg;
    hde_key key;

    if (!is_running)
    {
        return BCM_ERR_OK;
    }

    // We only look at message targetting epon links.
    if (rx->hdr.obj_type != BCMOLT_OBJ_ID_EPON_LINK)
    {
        // Not an error, we just don't care about this object.
        return BCM_ERR_OK;
    }

    // This is the only kind of proxy RX currently supported.
    if (rx->hdr.subgroup != BCMOLT_EPON_LINK_PROXY_RX_ID_FRAME_CAPTURED)
    {
        return BCM_ERR_OK;
    }

    // This is safe due to the above subgroup check.
    actual_rx = (bcmolt_epon_link_frame_captured*) rx;
    key.device_id = device_id;
    key.epon_ni = instance;
    key.mac_addr = actual_rx->key.mac_address;

    task_msg = bcmos_calloc(sizeof(*task_msg));
    if (task_msg == NULL)
    {
        rc = BCM_ERR_NOMEM;
    }
    else
    {
        bcmolt_msg *rx_clone = NULL;
        rc = bcmolt_msg_clone(&rx_clone, &rx->hdr);
        if (rc != BCM_ERR_OK)
        {
            bcmos_free(task_msg);
            return rc;
        }
        actual_rx = (bcmolt_epon_link_frame_captured*) rx_clone;

        task_msg->rx = rx_clone;
        task_msg->key = key;
        task_msg->event = HDE_EVENT_FRAME_RX;
        task_msg->os_msg.handler = hde_handle_event;
        rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &task_msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
        if (rc != BCM_ERR_OK)
        {
            BCM_LOG(ERROR, hde_data.log_id[device_id], "Message send failed!\n");
            bcmolt_msg_free(rx_clone);
        }
    }

    return rc;
}

void bcmolt_epon_hde_appl_cli_init(bcmcli_entry *top_dir)
{
    static const char *dir_name = "hde";

    if (bcmcli_dir_find(top_dir, dir_name))
    {
        return;
    }

    bcmcli_entry *dir = bcmcli_dir_add(top_dir, dir_name, "EPON OAM negotiation commands", BCMCLI_ACCESS_ADMIN, NULL);
    BUG_ON(dir == NULL);

    BCMCLI_MAKE_CMD(
        dir,
        "enable",
        "Enable encryption for an EPON link",
        hde_cli_enable,
        BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0),
        BCMCLI_MAKE_PARM("mac_address", "MAC address", BCMCLI_PARM_MAC, 0));

    BCMCLI_MAKE_CMD(
        dir,
        "disable",
        "Disable encryption for an EPON link",
        hde_cli_disable,
        BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0),
        BCMCLI_MAKE_PARM("mac_address", "MAC address", BCMCLI_PARM_MAC, 0));
}

void bcmolt_epon_hde_appl_init(void)
{
    bcmos_errno rc = BCM_ERR_OK;
    uint32_t i;

    bcmos_task_parm task_params =
    {
        .name = "user_appl_hde",
        .priority = TASK_PRIORITY_USER_APPL_EPON_HDE,
        .core = BCMOS_CPU_CORE_ANY, /* No CPU affinity */
        .init_handler = NULL
    };

    bcmos_timer_parm timer_parm =
    {
        .name = "oam_timeout_timer",
        .owner = BCMOS_MODULE_ID_NONE,
        .periodic = BCMOS_FALSE,
        .handler = oam_response_timeout
    };

    if (is_running)
    {
        return;
    }

    is_running = BCMOS_TRUE;

    for (i=0; i<BCMTR_MAX_OLTS; i++)
    {
        char log_name[MAX_DEV_LOG_ID_NAME];
        snprintf(log_name, sizeof(log_name)-1, "user_appl_hde_%d", i);
        hde_data.log_id[i] = bcm_dev_log_id_register(log_name, DEV_LOG_LEVEL_ERROR, DEV_LOG_ID_TYPE_BOTH);
    }

    hde_data.links = bcmos_calloc(HDE_MAX_NUM_LINKS * sizeof(hde_data.links[0]));
    BUG_ON(hde_data.links == NULL);

    rc = bcmos_task_create(&hde_data.task, &task_params);
    BUG_ON(rc != BCM_ERR_OK);

    bcmos_module_parm module_params =
    {
        .qparm = { .name = "user_appl_hde", .size = HDE_TASK_MSG_Q_SIZE }
    };
    rc = bcmos_module_create(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &hde_data.task, &module_params);
    BUG_ON(rc != BCM_ERR_OK);

    for (i = 0; i < HDE_MAX_NUM_LINKS; ++i)
    {
        timer_parm.data = i;
        rc = bcmos_timer_create(&hde_data.links[i].oam_timeout_timer, &timer_parm);
        BUG_ON(rc != BCM_ERR_OK);
    }
}
