/*****************************************************************************
 *                            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 LlcDecap
 * File:  llc_snap_decap.c
 * @description
 *    This file contains functions that perform LLC/SNAP header decapsulation
 *    and packet classification based on the protocol Id in the SNAP header.
 *    It also updates the packet's Meta data variables like packet size, offset.
 *
 *    Change History:
 *      April/06/2003    Created     Shreekanth Patel    Creation
 *****************************************************************************/

/*****************************************************************************
 *
 * Contents:
 *        Definitions of following exported functions
 *            LlcDecap()
 *
 *        Definitions of following local functions:
 *            LlcDecap_Classify
 *            LlcDecap_UpdateMeta
 *            LlcDecap_GetHeaderType
 *
 *****************************************************************************/

#ifndef	_LLC_SNAP_DECAP_C_
#define _LLC_SNAP_DECAP_C_

#include "llc_snap_decap.h"
#include "dl_system.h"
#include "dl_source.c"
#include "dl_meta.c"

#include "ixp.h"
#include "ixptypes.h"
#include "ixp_ipv4.c"

	
#define UNKNOWN_TYPE	0x00

/*****************************************************************************
 * Abstract:
 *    It returns the protocol id specified in the SNAP field of LLCSNAP header. 
 *
 * Assumptions:
 *****************************************************************************/
INLINE	int LlcDecap_GetHeaderType (UINT *p_pkt,UINT in_offset)
{
	int type;

	/*type = _buf_byte_extract((UINT*)p_pkt,in_offset, LLC_SNAP_HDR_SIZE, DRAM_RD_REG); */
	
	type = ixp_bytefield_extract(p_pkt[1], 2, 3, NO_LOAD_CC);


	return (type);

}

/***************************************************************************** 
 * Abstract:
 *    It updates the offset to the header, the sop buffer size and the packet
 *    size according to the L2 header size passed as input parameter.
 *
 * Assumptions:
 *****************************************************************************/
INLINE void	LlcDecap_UpdateMeta (void)
{
	/*  
	 * simply strip off the LLCSNAP header 
	 */

	dlMeta.offset += LLC_SNAP_HDR_SIZE;
	dlMeta.bufferSize -= LLC_SNAP_HDR_SIZE;
	dlMeta.packetSize -= LLC_SNAP_HDR_SIZE;

	return;
}

/*****************************************************************************
 * Abstract:
 *    It sets the header type field in packet meta data and the dl_next_block
 *    dispatch loop variable. 
 *
 * Assumptions:
 *****************************************************************************/
INLINE void	LlcDecap_Classify (void *p_pkt,UINT in_offset)
{
	int type;

	type = LlcDecap_GetHeaderType ((UINT *)p_pkt,in_offset);

	if (type == ETHER_IPV4_PID)
	{
		dlMeta.headerType = PKT_PROTO_IPv4;
		dlNextBlock = BID_IPV4;
#ifdef MPLS_INGRESS
		dlNextBlock = BID_CLASSIFIER_6T;
#endif
	}
	else if (type == ETHER_IPV6_PID)
	{
		dlMeta.headerType = PKT_PROTO_IPv6;
		dlNextBlock = BID_IPV6;
	}
	else if (type == ETHER_ARP_PID)
	{
		dlMeta.headerType = PKT_PROTO_ARP;
		dlNextBlock = BID_ARP;
	}
	else if (type == ETHER_PPP_DISCOVERY_PID)
	{
		dlMeta.headerType = PKT_PROTO_PPP_DISCOVERY;
		dlNextBlock = BID_PPP_DISCOVERY;
	}
	else if (type == ETHER_PPP_SESSION_PID)
	{
		dlMeta.headerType = PKT_PROTO_PPP_SESSION;
		dlNextBlock = BID_PPP_SESSION;
	}
	else
	{	dlMeta.headerType = UNKNOWN_TYPE;
		dlNextBlock = IX_EXCEPTION;
	
	}

	return;
}

/** 
 ****************************************************************************
 * @ingroup LlcDecap
 * LLCSNAP header decapsulation/protocol classifcation API function.
 *
 * @description
 *    It classifies the packet according to the header type specified in  
 *    meta data. Packet decapsulation is done by removing the LLC-SNAP header.
 *	  For MPLS packets there is no LLCSNAP header and packets are forwarded
 *    to MPLS blocks.
 *
 * @context
 *    It is called from the dispatch loop of the pipeline.
 *
 * @return 	Nothing                                                    
 ***************************************************************************/
INLINE void	LlcDecap (void *p_pkt, uint32_t in_offset)
{
	
	if (dlNextBlock != BID_LLC_SNAP_DECAP)
		return;

	/*  
	 * Check the header type set by AAL5 Rx block
	 * this is to if it is an IPv4 or MPLS packet
	 */
	if (dlMeta.headerType == PKT_PROTO_MPLS)
	{
		dlNextBlock = BID_ILM_FWDER;

	} 
    else if (dlMeta.headerType == PKT_PROTO_LLC_SNAP) 
	{
        LlcDecap_UpdateMeta ();
        LlcDecap_Classify (p_pkt,in_offset);
    }

	return;
}

#endif	/* _LLC_SNAP_DECAP_C_ */