/*****************************************************************************
 *                            Intel Proprietary
 *
 * Copyright (c) 1998-2002 By Intel Corporation.  All rights reserved.  
 * No part of this program or publication may be reproduced, transmitted,
 * transcribed, stored in a retrieval system, or translated into any language
 * or computer language in any form or by any means, electronic, mechanical,
 * magnetic, optical, chemical, manual, or otherwise, without the prior
 * written permission of:
 *                        Intel Corporation
 *                        2200 Mission College Blvd.
 *                        Santa Clara, CA  95052-8119
 *****************************************************************************/

/**
 *****************************************************************************
 * @ingroup LlcSnapEncap
 *
 * File:  ix_cc_llc_snap_encap_pkt_handlers.c
 *
 * @description
 *      This file defines the packet handling functions for the LLC Snap
 *      Encapsulation Core Component.
 *
 *****************************************************************************/

/*****************************************************************************
 *
 * Contents:
 *        Definitions of following exported data:
 *
 *        Definitions of following exported functions:
 *            ix_cc_llc_snap_encap_pkt_handler
 *
 *        Definitions of following local data:
 *
 *        Definitions of following local functions:
 *
 *****************************************************************************/


/*
 * User defined include files
 */
#include "ix_cc_llc_snap_encap.h"
#include "ix_cc_llc_snap_encap_private.h"


/**
 ****************************************************************************
 * @ingroup LlcSnapEncap
 * LLC Snap CC packet handler
 * @description
 *    This is the only registered function to receive exception
 *    packets from the LLC Snap Encap microblock.
 *
 * @param hBuffer - IN: handle to the buffer which contains
 *                     exception packets from the microblock
 * @param exceptionCode - IN: ignored in this case
 * @param pContext - IN: pointer to the context data
 *
 * @retval IX_SUCCESS - packet processed successfully
 * @retval IX_CC_ERROR_INTERNAL - error from CCI
 * @retval IX_CC_ERROR_SEND_FAIL - error sending the packet forth
 * @retval IX_CC_LLC_SNAP_ENCAP_ERROR_INVALID_INPUT_PARAM - invalid input
 *                                                          parameter(s)
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_pkt_handler(ix_buffer_handle hBuffer,  
                                 ix_uint32 exceptionCode,
                                 void* pContext)
{
    ix_error err = IX_SUCCESS;
    ix_cc_llc_snap_encap_pkt_lookup_result_t lookupResult;
    void *pData;
    ix_hw_buffer_meta *pMetaData;

    /* check input arguments' consistency */
    if (hBuffer == IX_NULL_BUFFER_HANDLE)
    {
        return IX_ERROR_WARNING(
        IX_CC_LLC_SNAP_ENCAP_ERROR_INVALID_INPUT_PARAM,
        ("LLC Snap Encap packet handler: hBuffer is NULL"));
    }

    if (pContext == NULL)
    {
        return IX_ERROR_WARNING(
        IX_CC_LLC_SNAP_ENCAP_ERROR_INVALID_INPUT_PARAM,
        ("LLC Snap Encap packet handler: pContext is NULL"));
    }

    /*  get packet data */
    err = ix_cc_hw_get_packet_data(hBuffer, &pData);

    /* attempt to free the buffer if getting data fails  */
    if (err) 
    {
        IX_ERROR_CRT(ix_rm_buffer_free_chain(hBuffer), 
                     IX_CC_ERROR_INTERNAL,
                     0);
        
        return IX_ERROR_CHAIN(
        err,
        IX_CC_ERROR_INTERNAL,
        0,
        ("LLC Snap Encap packet handler: Failed to get packet data"));
    }

    /*  get packet metadata */
    err = ix_rm_buffer_get_meta(hBuffer, (void **)&pMetaData);

    /* attempt to free the buffer if get data fails  */
    if (err) {
        IX_ERROR_CRT(ix_rm_buffer_free_chain(hBuffer), 
                     IX_CC_ERROR_INTERNAL,
                     0);
        
        return IX_ERROR_CHAIN(
        err,
        IX_CC_ERROR_INTERNAL,
        0, 
        ("LLC Snap Encap packet handler: Failed to get packet metadata"));
    }


    /* TEST CODE */

    /* dump the received packet's metadata onto the console */
    ix_ossl_message_log("LLC Snap Encap packet handler: Received packet metadata\n"
                        "m_HwNext     : 0x%8lx\n"
                        "m_BufferSize : %d\n"
                        "m_Offset     : %d\n"
                        "m_PacketSize : %d\n"
                        "m_BufferInfo : 0x%4x\n"
                        "m_InputPort  : %d\n"
                        "m_OutputPort : %d\n"
                        "m_NextHopID  : %d\n"
                        "m_FabricPort : %d\n"
                        "m_Reserved1  : %d\n"
                        "m_FlowID     : 0x%8x\n"
                        "m_ClassID    : 0x%4x\n"
                        "m_Reserved2  : %d\n"
                        "m_PacketNext : 0x%8lx\n",
                        pMetaData->m_HwNext, pMetaData->m_BufferSize, pMetaData->m_Offset, pMetaData->m_PacketSize,
                        pMetaData->m_BufferInfo, pMetaData->m_InputPort, pMetaData->m_OutputPort, pMetaData->m_NextHopID, 
                        pMetaData->m_FabricPort, pMetaData->m_Reserved1, pMetaData->m_FlowID,
                        pMetaData->m_ClassID, pMetaData->m_Reserved2, pMetaData->m_PacketNext);
    
    /* END TEST CODE */


    /* lookup the packet (ix_cc_xxx_search_entry ?) 
       lookupResult = ix_cc_xxx_search_entry(...); */

    /* update the packet metadata according to the lookup results */
    /* ... */

    /* use default next block if lookup failed */
    if (lookupResult.result != IX_SUCCESS)
    {
        lookupResult.nextBlockId = LLC_SNAP_ENCAP_DEFAULT_NEXT_BLOCK;
    }

    /* forward the packet according to the nextBlockId */
    switch (lookupResult.nextBlockId)
    {
	case LLC_SNAP_ENCAP_NEXT1:
	    /* send to default output */
	    err = ix_rm_packet_send(IX_CC_LLC_SNAP_ENCAP_DEFAULT_OUTPUT,
                                hBuffer,
                                0);
        if (err) 
	    {
            /* Free the buffer and return error to caller */
        	IX_ERROR_CRT(ix_rm_buffer_free(hBuffer), IX_CC_ERROR_INTERNAL, 0);
            
        	return IX_ERROR_CHAIN(
            err,
            IX_CC_ERROR_SEND_FAIL,
            0, 
            ("LLC Snap Encap packet handler: Failed to send packet to"
             " IX_CC_LLC_SNAP_ENCAP_DEFAULT_OUTPUT"));
        }
        
	    break;

	case LLC_SNAP_ENCAP_NEXT2:
	    /* send to FWD output */
	    err = ix_rm_packet_send(IX_CC_LLC_SNAP_ENCAP_FWD_OUTPUT,
                                hBuffer,
                                0);
        if (err) 
	    {
            /* Free the buffer and return error to caller */
        	IX_ERROR_CRT(ix_rm_buffer_free(hBuffer),
                         IX_CC_ERROR_INTERNAL,
                         0);
            
        	return IX_ERROR_CHAIN(
            err,
            IX_CC_ERROR_SEND_FAIL,
            0, 
            ("LLC Snap Encap packet handler: Failed to send packet to"
             " IX_CC_LLC_SNAP_ENCAP_FWD_OUTPUT"));
        }
        
	    break;

	case LLC_SNAP_ENCAP_NEXT3:
	    /* drop the packet */
	    IX_ERROR_CRT(ix_rm_buffer_free_chain(hBuffer),
                     IX_CC_ERROR_INTERNAL,
                     0);
	    break;

	default:
        return IX_ERROR_WARNING(IX_CC_ERROR_SEND_FAIL,
                                ("LLC Snap Encap packet handler: unknown next block ID"));
    }

    /* check the exception code
       switch(arg_ExceptionCode)
       {
       default:
       IX_ERROR_CRT(ix_rm_buffer_free_chain(hBuffer),IX_CC_ERROR_SEND_FAIL,0);
       return IX_ERROR_WARNING(IX_CC_ERROR_UNDEFINED_EXCEP,
       ("undefined exception code"));
       break;
       }
    */
   
    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_pkt_handler */

