#ifndef ARM_TRC_PKT_PROC_BASE_H_INCLUDED
#define ARM_TRC_PKT_PROC_BASE_H_INCLUDED
#include <new>
#include "interfaces/trc_data_raw_in_i.h"
#include "interfaces/trc_pkt_in_i.h"
#include "interfaces/trc_pkt_raw_in_i.h"
#include "interfaces/trc_indexer_pkt_i.h"
#include "trc_component.h"
#include "comp_attach_pt_t.h"
#include "opencsd/ocsd_if_version.h"
class TrcPktProcI : public TraceComponent, public ITrcDataIn
{
public:
TrcPktProcI(const char *component_name);
TrcPktProcI(const char *component_name, int instIDNum);
virtual ~TrcPktProcI() {};
virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op,
const ocsd_trc_index_t index,
const uint32_t dataBlockSize,
const uint8_t *pDataBlock,
uint32_t *numBytesProcessed) = 0;
virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats) = 0;
virtual void resetStats() = 0;
protected:
virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index,
const uint32_t dataBlockSize,
const uint8_t *pDataBlock,
uint32_t *numBytesProcessed) = 0;
virtual ocsd_datapath_resp_t onEOT() = 0; virtual ocsd_datapath_resp_t onReset() = 0; virtual ocsd_datapath_resp_t onFlush() = 0; virtual ocsd_err_t onProtocolConfig() = 0; virtual const bool isBadPacket() const = 0; };
inline TrcPktProcI::TrcPktProcI(const char *component_name) :
TraceComponent(component_name)
{
}
inline TrcPktProcI::TrcPktProcI(const char *component_name, int instIDNum) :
TraceComponent(component_name,instIDNum)
{
}
template <class P, class Pt, class Pc>
class TrcPktProcBase : public TrcPktProcI
{
public:
TrcPktProcBase(const char *component_name);
TrcPktProcBase(const char *component_name, int instIDNum);
virtual ~TrcPktProcBase();
virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op,
const ocsd_trc_index_t index,
const uint32_t dataBlockSize,
const uint8_t *pDataBlock,
uint32_t *numBytesProcessed);
componentAttachPt<IPktDataIn<P>> *getPacketOutAttachPt() { return &m_pkt_out_i; };
componentAttachPt<IPktRawDataMon<P>> *getRawPacketMonAttachPt() { return &m_pkt_raw_mon_i; };
componentAttachPt<ITrcPktIndexer<Pt>> *getTraceIDIndexerAttachPt() { return &m_pkt_indexer_i; };
virtual ocsd_err_t setProtocolConfig(const Pc *config);
virtual const Pc *getProtocolConfig() const { return m_config; };
virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats);
virtual void resetStats();
protected:
ocsd_datapath_resp_t outputDecodedPacket(const ocsd_trc_index_t index_sop, const P *pkt);
void outputRawPacketToMonitor( const ocsd_trc_index_t index_sop,
const P *pkt,
const uint32_t size,
const uint8_t *p_data);
void indexPacket(const ocsd_trc_index_t index_sop, const Pt *packet_type);
ocsd_datapath_resp_t outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, std::vector<uint8_t> &pktdata);
ocsd_datapath_resp_t outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, const uint8_t *pktdata, uint32_t pktlen);
const bool hasRawMon() const;
const Pc *m_config;
void ClearConfigObj();
const bool checkInit();
void statsAddTotalCount(const uint64_t count) { m_stats.channel_total += count; };
void statsAddUnsyncCount(const uint64_t count) { m_stats.channel_unsynced += count; };
void statsAddBadSeqCount(const uint32_t count) { m_stats.bad_sequence_errs += count; };
void statsAddBadHdrCount(const uint32_t count) { m_stats.bad_header_errs += count; };
void statsInit() { m_stats_init = true; };
private:
ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index);
ocsd_datapath_resp_t Flush();
ocsd_datapath_resp_t EOT();
componentAttachPt<IPktDataIn<P>> m_pkt_out_i;
componentAttachPt<IPktRawDataMon<P>> m_pkt_raw_mon_i;
componentAttachPt<ITrcPktIndexer<Pt>> m_pkt_indexer_i;
bool m_b_is_init;
ocsd_decode_stats_t m_stats;
bool m_stats_init;
};
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name) :
TrcPktProcI(component_name),
m_config(0),
m_b_is_init(false),
m_stats_init(false)
{
resetStats();
}
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name, int instIDNum) :
TrcPktProcI(component_name, instIDNum),
m_config(0),
m_b_is_init(false),
m_stats_init(false)
{
resetStats();
}
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::~TrcPktProcBase()
{
ClearConfigObj();
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::TraceDataIn( const ocsd_datapath_op_t op,
const ocsd_trc_index_t index,
const uint32_t dataBlockSize,
const uint8_t *pDataBlock,
uint32_t *numBytesProcessed)
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
switch(op)
{
case OCSD_OP_DATA:
if((dataBlockSize == 0) || (pDataBlock == 0) || (numBytesProcessed == 0))
{
if(numBytesProcessed)
*numBytesProcessed = 0; LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL,"Packet Processor: Zero length data block or NULL pointer error\n"));
resp = OCSD_RESP_FATAL_INVALID_PARAM;
}
else
resp = processData(index,dataBlockSize,pDataBlock,numBytesProcessed);
break;
case OCSD_OP_EOT:
resp = EOT();
break;
case OCSD_OP_FLUSH:
resp = Flush();
break;
case OCSD_OP_RESET:
resp = Reset(index);
break;
default:
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL,"Packet Processor : Unknown Datapath operation\n"));
resp = OCSD_RESP_FATAL_INVALID_OP;
break;
}
return resp;
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Reset(const ocsd_trc_index_t index)
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
if(m_pkt_out_i.hasAttachedAndEnabled())
resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_RESET,index,0);
if(!OCSD_DATA_RESP_IS_FATAL(resp))
resp = onReset();
if(m_pkt_raw_mon_i.hasAttachedAndEnabled())
m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_RESET,index,0,0,0);
return resp;
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Flush()
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
ocsd_datapath_resp_t resplocal = OCSD_RESP_CONT;
if(m_pkt_out_i.hasAttachedAndEnabled())
resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_FLUSH,0,0);
if(OCSD_DATA_RESP_IS_CONT(resp))
resplocal = onFlush();
return (resplocal > resp) ? resplocal : resp;
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::EOT()
{
ocsd_datapath_resp_t resp = onEOT();
if(m_pkt_out_i.hasAttachedAndEnabled() && !OCSD_DATA_RESP_IS_FATAL(resp))
resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_EOT,0,0);
if(m_pkt_raw_mon_i.hasAttachedAndEnabled())
m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_EOT,0,0,0,0);
return resp;
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::outputDecodedPacket(const ocsd_trc_index_t index, const P *pkt)
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
if((getComponentOpMode() & OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS) && isBadPacket())
return resp;
if(m_pkt_out_i.hasAttachedAndEnabled())
resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_DATA,index,pkt);
return resp;
}
template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::outputRawPacketToMonitor(
const ocsd_trc_index_t index_sop,
const P *pkt,
const uint32_t size,
const uint8_t *p_data)
{
if(size == 0)
return;
if((getComponentOpMode() & OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS) && isBadPacket())
return;
if(m_pkt_raw_mon_i.hasAttachedAndEnabled())
m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_DATA,index_sop,pkt,size,p_data);
}
template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::hasRawMon() const
{
return m_pkt_raw_mon_i.hasAttachedAndEnabled();
}
template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::indexPacket(const ocsd_trc_index_t index_sop, const Pt *packet_type)
{
if(m_pkt_indexer_i.hasAttachedAndEnabled())
m_pkt_indexer_i.first()->TracePktIndex(index_sop,packet_type);
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, std::vector<uint8_t> &pktdata)
{
indexPacket(index_sop,pkt_type);
if(pktdata.size() > 0) outputRawPacketToMonitor(index_sop,pkt,(uint32_t)pktdata.size(),&pktdata[0]);
return outputDecodedPacket(index_sop,pkt);
}
template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, const uint8_t *pktdata, uint32_t pktlen)
{
indexPacket(index_sop,pkt_type);
outputRawPacketToMonitor(index_sop,pkt,pktlen,pktdata);
return outputDecodedPacket(index_sop,pkt);
}
template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::setProtocolConfig(const Pc *config)
{
ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL;
if(config != 0)
{
ClearConfigObj();
m_config = new (std::nothrow) Pc(*config);
if(m_config != 0)
err = onProtocolConfig();
else
err = OCSD_ERR_MEM;
}
return err;
}
template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::ClearConfigObj()
{
if(m_config)
{
delete m_config;
m_config = 0;
}
}
template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::checkInit()
{
if(!m_b_is_init)
{
if( (m_config != 0) &&
(m_pkt_out_i.hasAttached() || m_pkt_raw_mon_i.hasAttached())
)
m_b_is_init = true;
}
return m_b_is_init;
}
template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::getStatsBlock(ocsd_decode_stats_t **pp_stats)
{
*pp_stats = &m_stats;
return m_stats_init ? OCSD_OK : OCSD_ERR_NOT_INIT;
}
template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::resetStats()
{
m_stats.version = OCSD_VER_NUM;
m_stats.revision = OCSD_STATS_REVISION;
m_stats.channel_total = 0;
m_stats.channel_unsynced = 0;
m_stats.bad_header_errs = 0;
m_stats.bad_sequence_errs = 0;
m_stats.demux.frame_bytes = 0;
m_stats.demux.no_id_bytes = 0;
m_stats.demux.valid_id_bytes = 0;
}
#endif