/**
 * ============================================================================
 * = 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) 2002 Intel Corporation. All rights reserved.
 *
 * 
 *      
 *
 * = MODULE
 *     IPv4 Core Component - ICMP module 
 *
 * = FILENAME
 *      icmp_queue.c
 *
 * = DESCRIPTION
 *     This file contains the implementation of
 *     ICMP queue for rate-limiting of ICMP error
 *     messages.  
 * 
 *      
 *
 * = CREATION TIME
 *      6/14/2002 7:56:24 PM
 *
 * = CHANGE HISTORY
 *
 * ============================================================================
 */

#define IX_ERROR_FILE_IDENT "$Id: icmp_queue.c,v 1.15 2003/11/17 19:42:04 rranjeet Exp $"


/**
 * System defined include files required.
 */
#include "ix_cc_error.h"
#include "ix_ossl.h"

/**
 * User defined include files required.
 */
#include "cc/ipv4/internal/icmp_queue.h"
/**
 * Preprocessor symbols and macros used in this file.
 */

/**
 * Types definitions whose scope is limited to this file.
 */

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

/**
 * Extern function prototypes.
 */

/**
 * Exported variables.
 */
ix_buffer_handle g_IcmpQueue[IX_CC_IPV4_ICMPQ_MAXSIZE];
ix_uint32 g_IcmpQhead;
ix_uint32 g_IcmpQtail;

/**
 * Static function prototypes.
 */

/**
 * Function definitions.
 */
void _ix_cc_ipv4_icmp_queue_init()
{
    g_IcmpQhead = 0;
    g_IcmpQtail = 0;
	
    
}


ix_error _ix_cc_ipv4_icmp_queue_enqueue(ix_buffer_handle arg_hBuffer,
                                       ix_uint32 *arg_pEnqueue)
{
#ifdef DUMP_TO_SCREEN
    void *pData;
    register ix_uint32 i=0;
    ix_uint8 *pTemp;  

#endif
   
    if (IX_CC_IPV4_ICMP_IS_QUEUE_FULL(g_IcmpQhead, g_IcmpQtail))
    {
        *arg_pEnqueue = 1;
        return IX_SUCCESS;
    }
#ifdef DUMP_TO_SCREEN
   
    IX_ERROR_CRT(ix_cc_hw_get_packet_data(arg_hBuffer, &pData),
         IX_CC_ERROR_INTERNAL, 0);
    pTemp = ix_ossl_malloc(48);
    ix_ossl_memcpy(pTemp, pData, 48);
    ix_ossl_message_log("Printing the buffer that I am enqueuing" 
		"in fn ix_cc_ipv4_icmp_queue_enqueue\n");


    for ( i=0;i < 48; i++)
    {
        ix_ossl_message_log("%02x ", pTemp[i]);
        if ( (i+1) % 4 == 0)
        {
            ix_ossl_message_log("\n");
        }
    }
    ix_ossl_message_log("\n");
    ix_ossl_free(pTemp);

#endif /* DUMP_TO_SCREEN */

    g_IcmpQueue[g_IcmpQtail] = arg_hBuffer;
    g_IcmpQtail = (g_IcmpQtail + 1) % IX_CC_IPV4_ICMPQ_MAXSIZE;
    
    *arg_pEnqueue = 0;
    return IX_SUCCESS;
}



ix_error _ix_cc_ipv4_icmp_queue_dequeue(ix_buffer_handle *arg_phBuffer,
					 ix_uint32 *arg_pDequeue)
{
#ifdef DUMP_TO_SCREEN
    
    void *pData;
    register ix_uint32 i=0;
    ix_uint8 *pTemp;         
#endif

    if (IX_CC_IPV4_ICMP_IS_QUEUE_EMPTY(g_IcmpQhead, g_IcmpQtail))
    {
        *arg_pDequeue = 1;
        return IX_SUCCESS;

    }
    
    
    *arg_phBuffer = g_IcmpQueue[g_IcmpQhead];

#ifdef DUMP_TO_SCREEN
       
    IX_ERROR_CRT(ix_cc_hw_get_packet_data((*arg_phBuffer), &pData),
            IX_CC_ERROR_INTERNAL, 0);

    pTemp = ix_ossl_malloc(48);
    ix_ossl_memcpy(pTemp, pData, 48);
    ix_ossl_message_log("Printing the buffer that I am dequeuing" 
		"in fn ix_cc_ipv4_icmp_queue_dequeue\n");
    for ( i=0;i < 48; i++)
    {
        ix_ossl_message_log("%02x ", pTemp[i]);
        if ( (i+1) % 4 == 0)
        {
            ix_ossl_message_log("\n");
        }
    }
    ix_ossl_message_log("\n");
    ix_ossl_free(pTemp); 

#endif /* DUMP_TO_SCREEN */

    g_IcmpQhead = (g_IcmpQhead + 1) % IX_CC_IPV4_ICMPQ_MAXSIZE;
    *arg_pDequeue = 0;
    return IX_SUCCESS;
}

ix_error _ix_cc_ipv4_icmp_print_queue() 
{
    register ix_uint32 i=0, j=0;
    
    void *pData;
    ix_uint8 *pTemp;
    ix_uint32 size = IX_CC_IPV4_ICMP_GET_QUEUE_SIZE(g_IcmpQhead, g_IcmpQtail);
   
    ix_ossl_message_log("Head: %ld\n", g_IcmpQhead);
    ix_ossl_message_log("Tail: %ld\n", g_IcmpQtail);
    
    ix_ossl_message_log("* == location of head pointer\n");
    ix_ossl_message_log("# == location of tail pointer\n");
    for (i=0;i< size; i++)
    {
        if (i == g_IcmpQhead)
        {
            ix_ossl_message_log("*");
        }
        if (i == g_IcmpQtail)
        {
            ix_ossl_message_log("#");
        }
		


        IX_ERROR_CRT(ix_cc_hw_get_packet_data(g_IcmpQueue[i], &pData),
        IX_CC_ERROR_INTERNAL, 0);
        pTemp = ix_ossl_malloc(48);
        ix_ossl_memcpy(pTemp, pData, 48);
#ifdef DUMP_TO_SCREEN
        ix_ossl_message_log("Printing the buffer that is in queue" 
		"in fn ix_cc_ipv4_icmp_print_queue at location i = %d\n", i);
#endif
        for ( j=0;j < 48; j++)
        {
            ix_ossl_message_log("%02x ", pTemp[j]);
            if ( (j+1) % 4 == 0)
            {
                ix_ossl_message_log("\n");
            }
        }
        ix_ossl_message_log("\n");
        ix_ossl_free(pTemp);
        pData = NULL;

    }
    ix_ossl_message_log("\n");
    return IX_SUCCESS;
}

ix_error _ix_cc_ipv4_icmp_dump_queue(ix_uint32 arg_BufferSize,
                                    ix_buffer_handle *arg_phBuffer)
{
    register ix_uint32 i=0;
    ix_uint32 size = 
          IX_CC_IPV4_ICMP_GET_QUEUE_SIZE(g_IcmpQhead, g_IcmpQtail);
    if (arg_phBuffer == NULL)
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
        ("The buffer handle pointer is null\n"));

    for (i=0;i< size; i++)
    {
        if (i >= arg_BufferSize -1)
        {
            break;
        }
        arg_phBuffer[i] = g_IcmpQueue[i];
    }
    arg_phBuffer[i] = 0;

    if (i != size)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_FULL,
            ("There wasn't enough room to store all the results\n"
             "\tNeed to have a buffer big enough for %d entries",
             size));
	
    }
    
    return IX_SUCCESS;
}
