/**
 * ============================================================================
 * = COPYRIGHT
 *              INTEL CORPORATION PROPRIETARY INFORMATION
 *   This software is supplied under the terms of a license agreement or
 *   nondisclosure agreement with Intel Corporation and may not be copied 
 *   or disclosed except in accordance with the terms in that agreement.
 *      Copyright (C) 2000-2001 Intel Corporation. All rights reserved.
 *
 * = PRODUCT
 *      Intel(r) IXA SDK 3.0 for the IXP2000 Network Processor, Release 5
 *
 * = LIBRARY
 *      
 *
 * = MODULE
 *      IPv4 Forwarder Core Component - packet handlers
 *
 * = FILENAME
 *      ix_cc_ipv4_pkt_handlers.c
 *
 * = DESCRIPTION
 *      The file defines packet handler interface functions.
 *
 * = AUTHOR
 *       Govindan Nair
 *       govindan.nair@intel.com
 *
 * = AKNOWLEDGEMENTS
 *      
 *
 * = CREATION TIME
 *      07/08/2002
 *
 * = CHANGE HISTORY
 *
 * ============================================================================
 */
#define IX_ERROR_FILE_IDENT "$Id: ix_cc_ipv4_pkt_handlers.c,v 1.21 2003/12/12 00:47:19 ktseng Exp $";

#include "ix_ossl.h"
#include "ix_rm.h"

#include "ix_cc_error.h"
#include "cc/ix_cc_rtmv4.h"

#include "ix_cc.h"
#include "bindings.h"
#include "ipv4_fwder_uc.h"
#include "cc/ix_cc_ipv4.h"
#include "cc/ipv4/internal/ix_cc_ipv4_init.h"
#include "cc/ipv4/internal/icmp.h"
#include "cc/ipv4/internal/fragmentation_support.h"
#include "cc/ipv4/internal/header_defs.h"
#include "cc/ipv4/internal/ipv4_fwdr.h"
#include "../../../../library/dataplane_library/microcode/ipv4.h"





/**
 * Preprocessor symbols and Macros used in this file
 */

/**
 * Type definitions whose scope is limited to this file
 */


/**
 * Variable declarations global to this file only. Externs are followed by 
 * static variables.
 */


/** 
 * Extern function prototypes.
 */


extern ix_cc_ipv4_context* g_pIpv4Context;
extern ix_error _ix_cc_ipv4_forward(ix_buffer_handle arg_hBuffer);
extern ix_error _ix_cc_ipv4_forward_pkts_from_stkdrvr(ix_buffer_handle arg_hBuffer);  

/** 
 * Static function prototypes.
 */


/** 
 * Function definitions.
 */



/**
 * NAME: ix_cc_ipv4_microblock_high_priority_pkt_handler
 *
 * DESCRIPTION: This is the only registered function to receive exception packets from
 * high priority queue of IPv4 microblock. This function sends the packet to stack driver
 * (ie, recieves only local delivery packets). 
 * 
 * @Param:  - IN arg_hBuffer: handle to a buffer which contains exception packets
 *  from IPv4 microblock
 * @Param: - IN arg_ExceptionCode: will be ignored.
 * @Param: - IN arg_pContext: pointer to IPV4 Forwarder core component context.
 * @Param:  - OUT none
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_ERROR_SEND_FAIL - error from CCI
 * 
 */

ix_error ix_cc_ipv4_microblock_high_priority_pkt_handler(
                                                         ix_buffer_handle arg_hBuffer,  
                                                         ix_uint32 arg_ExceptionCode,
                                                         void* arg_pContext
                                                        )
{

    ix_error err = IX_SUCCESS;

  
    switch(arg_ExceptionCode)
    {
    case IPV4_EXCP_OPTIONS:

        return _ix_cc_ipv4_process_options(arg_hBuffer);

        break;
    case IPV4_EXCP_LOCAL_DELIVERY:
        err = ix_rm_message_send(IX_CC_IPV4_PKT_HIGH_PRIORITY_STKDRV_OUTPUT,arg_hBuffer,0);
        break;
    default:
        IX_ERROR_CRT(ix_rm_buffer_free_chain(arg_hBuffer),IX_CC_ERROR_SEND_FAIL,0);
        return IX_ERROR_WARNING(IX_CC_ERROR_UNDEFINED_EXCEP,
                               ("undefined exception code"));
        break;
    }/* end switch */


    if(err != IX_SUCCESS)
    {
        IX_ERROR_CRT(ix_rm_buffer_free_chain(arg_hBuffer),IX_CC_ERROR_SEND_FAIL,0);
        return IX_ERROR_WARNING(IX_CC_ERROR_SEND_FAIL,
                                ("packet send failed - high priority"));
    }/* end if (err != IX_SUCCESS) */     

   
   return IX_SUCCESS;

} /* end ix_cc_ipv4_microblock_high_priority_pkt_handler */




/**
 * NAME: ix_cc_ipv4_microblock_low_priority_pkt_handler
 *
 * DESCRIPTION: This is the registered function to receive exception packets from 
 * IPv4 microblock. This function internally calls/performs different 
 * functions/operations based on exception code for the given packet.
 * 
 * @Param:  - IN arg_hBuffer: handle to a buffer which contains exception packets
 * from IPv4 microblock
 * @Param: - IN arg_ExceptionCode: Exception codes generated by IPv4 forwarder microblock.
 * @Param: - IN arg_pContext: pointer to IPV4 Forwarder core component context
 * @Param:  - OUT none
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_ERROR_SEND_FAIL - error from CCI
 * IX_CC_ERROR_UNDEFINED_EXCEP - unsupported exception code
 * IX_CC_ERROR_INTERNAL - an internal error
 * IX_CC_ERROR_ALIGN - pointer not aligned properly
 * IX_CC_ERROR_NULL - null pointer
 * IX_CC_IPV4_ERROR_RTM - error from RTM
 */


ix_error ix_cc_ipv4_microblock_low_priority_pkt_handler(
                                                        ix_buffer_handle arg_hBuffer,  
                                                        ix_uint32 arg_ExceptionCode,
                                                        void* arg_pContext
                                                       )
{
    ix_error err = IX_SUCCESS;
    ix_uint8 reason;
    
    switch(arg_ExceptionCode)
    {
    case IPV4_EXCP_LENGTH_MISMATCH:
        err = _ix_cc_ipv4_icmp_param_problem(arg_hBuffer,IX_ICMP_PARAM_TOTALLENGTH);
        break;
    case IPV4_EXCP_BAD_TTL:
        err = _ix_cc_ipv4_icmp_time_exceeded(arg_hBuffer);
        break;
    case IPV4_EXCP_FRAG_REQUIRED:
    case IPV4_EXCP_REDIRECT:
        err = _ix_cc_ipv4_forward(arg_hBuffer);
        break;
    case IPV4_EXCP_DOWN:
    case IPV4_EXCP_NO_ROUTE:
        reason = IX_ICMP_UNREACH_HOST;
        err = _ix_cc_ipv4_icmp_dest_unreachable(arg_hBuffer,reason,0);
        break;
    case IPV4_EXCP_BROADCAST:
    case IPV4_EXCP_MULTICAST:
        err = ix_rm_packet_send(IX_CC_IPV4_PKT_LOW_PRIORITY_STKDRV_OUTPUT,arg_hBuffer,0);
        if(err != IX_SUCCESS)
        {
            IX_ERROR_CRT(ix_rm_buffer_free_chain(arg_hBuffer),IX_CC_ERROR_SEND_FAIL,0);
            return IX_ERROR_NEW(IX_CC_ERROR_SEND_FAIL, IX_ERROR_LEVEL_WARNING);
			/*	return IX_ERROR_WARNING(IX_CC_ERROR_SEND_FAIL,
                                   ("packet send failed")); */

        }/* end if (err != IX_SUCCESS) */
        break;    
    default:
        IX_ERROR_CRT(ix_rm_buffer_free_chain(arg_hBuffer),IX_CC_ERROR_SEND_FAIL,0);
        return IX_ERROR_WARNING(IX_CC_ERROR_UNDEFINED_EXCEP,
                               ("undefined exception code"));
        break;
    }/* end switch */

   
    return err;

} /* end ix_cc_ipv4_microblock_low_priority_pkt_handler */



/**
 * NAME: ix_cc_ipv4_stkdrv_pkt_handler
 *
 * DESCRIPTION: This is the registered function to receive packets from stack driver 
 * core component. 
 *
 * @Param:  - IN arg_hBuffer: handle to a buffer which contains packet
 * from stack driver core component. - 
 *
 * @Param:  - IN arg_ExceptionCode:  will be Ignored 
 *
 * @Param:  - IN arg_pContext: pointer to IPV4 Forwarder core component context.
 * @Param:  - OUT none
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_ERROR_SEND_FAIL - error from CCI
 * IX_CC_ERROR_INTERNAL - an internal error
 * IX_CC_ERROR_ALIGN - pointer not aligned properly
 * IX_CC_ERROR_NULL - null pointer
 * 
 */

ix_error ix_cc_ipv4_stkdrv_pkt_handler(
                                       ix_buffer_handle arg_hBuffer,  
                                       ix_uint32 arg_ExceptionCode,
                                       void* arg_pContext
                                      )
{
 
    /* Call ipv4 forward function */
    return _ix_cc_ipv4_forward_pkts_from_stkdrvr(arg_hBuffer); 
   
} /* end ix_cc_ipv4_stkdrv_pkt_handler */


/**
 * NAME: ix_cc_ipv4_common_pkt_handler
 *
 * DESCRIPTION: This is the registered function to receive packets 
 * from any core component other than stack driver.
 * 
 * @Param:  - IN arg_hBuffer: handle to a buffer which contains packet from any core component other than stack driver.
 * @Param:  - INarg_ExceptionCode:  will be Ignored
 * @Param:  - INarg_pContext: pointer to IPV4 Forwarder core component context 
 * @Param:  - OUT none
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_ERROR_INTERNAL - an internal error
 * IX_CC_ERROR_ALIGN - pointer not aligned properly
 * IX_CC_ERROR_NULL - null pointer
 * IX_CC_ERROR_SEND_FAIL - error from CCI
 * 
 */

ix_error ix_cc_ipv4_common_pkt_handler(
                                ix_buffer_handle arg_hBuffer,  
                                ix_uint32 arg_ExceptionCode,
                                void* arg_pContext
                                )
{

    /* Call ipv4 forward function */
    return   _ix_cc_ipv4_forward_pkts_from_cc(arg_hBuffer); 

   
} /* end ix_cc_ipv4_common_pkt_handler */
