1 /*! 2 * \file trc_pkt_proc_base.h 3 * \brief OpenCSD : Trace packet processor base class. 4 * 5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. 6 */ 7 8 9 /* 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 20 * 3. Neither the name of the copyright holder nor the names of its contributors 21 * may be used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #ifndef ARM_TRC_PKT_PROC_BASE_H_INCLUDED 37 #define ARM_TRC_PKT_PROC_BASE_H_INCLUDED 38 39 #include "interfaces/trc_data_raw_in_i.h" 40 #include "interfaces/trc_pkt_in_i.h" 41 #include "interfaces/trc_pkt_raw_in_i.h" 42 #include "interfaces/trc_indexer_pkt_i.h" 43 44 #include "trc_component.h" 45 #include "comp_attach_pt_t.h" 46 47 /** @defgroup ocsd_pkt_proc OpenCSD Library : Packet Processors. 48 @brief Classes providing Protocol Packet Processing capability. 49 50 Packet processors take an incoming byte stream and convert into discrete packets for the 51 required trace protocol. 52 @{*/ 53 54 55 56 /*! 57 * @class TrcPktProcI 58 * @brief Base Packet processing interface 59 * 60 * Defines the packet processing methods that protocol specific processors must 61 * implement. 62 * 63 */ 64 class TrcPktProcI : public TraceComponent, public ITrcDataIn 65 { 66 public: 67 TrcPktProcI(const char *component_name); 68 TrcPktProcI(const char *component_name, int instIDNum); 69 virtual ~TrcPktProcI() {}; 70 71 /** Trace byte data input interface - from ITrcDataIn. 72 */ 73 virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, 74 const ocsd_trc_index_t index, 75 const uint32_t dataBlockSize, 76 const uint8_t *pDataBlock, 77 uint32_t *numBytesProcessed) = 0; 78 79 protected: 80 81 /* implementation packet processing interface */ 82 83 /*! @brief Implementation function for the OCSD_OP_DATA operation */ 84 virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, 85 const uint32_t dataBlockSize, 86 const uint8_t *pDataBlock, 87 uint32_t *numBytesProcessed) = 0; 88 89 virtual ocsd_datapath_resp_t onEOT() = 0; //!< Implementation function for the OCSD_OP_EOT operation 90 virtual ocsd_datapath_resp_t onReset() = 0; //!< Implementation function for the OCSD_OP_RESET operation 91 virtual ocsd_datapath_resp_t onFlush() = 0; //!< Implementation function for the OCSD_OP_FLUSH operation 92 virtual ocsd_err_t onProtocolConfig() = 0; //!< Called when the configuration object is passed to the decoder. 93 virtual const bool isBadPacket() const = 0; //!< check if the current packet is an error / bad packet 94 }; 95 96 inline TrcPktProcI::TrcPktProcI(const char *component_name) : 97 TraceComponent(component_name) 98 { 99 } 100 101 inline TrcPktProcI::TrcPktProcI(const char *component_name, int instIDNum) : 102 TraceComponent(component_name,instIDNum) 103 { 104 } 105 106 /*! 107 * @class TrcPktProcBase 108 * @brief Packet Processor base class. Provides common infrastructure and interconnections for packet processors. 109 * 110 * The class is a templated base class. 111 * - P - this is the packet object class. 112 * - Pt - this is the packet type class. 113 * - Pc - this is the packet configuration class. 114 * 115 * implementations will provide concrete classes for each of these to operate under the common infrastructures. 116 * The base provides the trace data in (ITrcDataIn) interface and operates on the incoming operation type. 117 * 118 * Implementions override the 'onFn()' and data process functions defined in TrcPktProcI, 119 * with the base class ensuring consistent ordering of operations. 120 * 121 */ 122 template <class P, class Pt, class Pc> 123 class TrcPktProcBase : public TrcPktProcI 124 { 125 public: 126 TrcPktProcBase(const char *component_name); 127 TrcPktProcBase(const char *component_name, int instIDNum); 128 virtual ~TrcPktProcBase(); 129 130 /** Byte trace data input interface defined in ITrcDataIn 131 132 The base class implementation processes the operation to call the 133 interface functions on TrcPktProcI. 134 */ 135 virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, 136 const ocsd_trc_index_t index, 137 const uint32_t dataBlockSize, 138 const uint8_t *pDataBlock, 139 uint32_t *numBytesProcessed); 140 141 142 /* component attachment points */ 143 144 //! Attachement point for the protocol packet output 145 componentAttachPt<IPktDataIn<P>> *getPacketOutAttachPt() { return &m_pkt_out_i; }; 146 //! Attachment point for the protocol packet monitor 147 componentAttachPt<IPktRawDataMon<P>> *getRawPacketMonAttachPt() { return &m_pkt_raw_mon_i; }; 148 149 //! Attachment point for a packet indexer 150 componentAttachPt<ITrcPktIndexer<Pt>> *getTraceIDIndexerAttachPt() { return &m_pkt_indexer_i; }; 151 152 /* protocol configuration */ 153 //!< Set the protocol specific configuration for the decoder. 154 virtual ocsd_err_t setProtocolConfig(const Pc *config); 155 //!< Get the configuration for the decoder. 156 virtual const Pc *getProtocolConfig() const { return m_config; }; 157 158 protected: 159 160 /* data output functions */ 161 ocsd_datapath_resp_t outputDecodedPacket(const ocsd_trc_index_t index_sop, const P *pkt); 162 163 void outputRawPacketToMonitor( const ocsd_trc_index_t index_sop, 164 const P *pkt, 165 const uint32_t size, 166 const uint8_t *p_data); 167 168 void indexPacket(const ocsd_trc_index_t index_sop, const Pt *packet_type); 169 170 ocsd_datapath_resp_t outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, std::vector<uint8_t> &pktdata); 171 172 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); 173 174 /*! Let the derived class figure out if it needs to collate and send raw data. 175 can improve wait for sync performance if we do not need to save and send unsynced data. 176 */ 177 const bool hasRawMon() const; 178 179 /* the protocol configuration */ 180 const Pc *m_config; 181 182 void ClearConfigObj(); // remove our copy of the config 183 184 const bool checkInit(); // return true if init (configured and at least one output sink attached), false otherwise. 185 186 private: 187 /* decode control */ 188 ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index); 189 ocsd_datapath_resp_t Flush(); 190 ocsd_datapath_resp_t EOT(); 191 192 componentAttachPt<IPktDataIn<P>> m_pkt_out_i; 193 componentAttachPt<IPktRawDataMon<P>> m_pkt_raw_mon_i; 194 195 componentAttachPt<ITrcPktIndexer<Pt>> m_pkt_indexer_i; 196 197 bool m_b_is_init; 198 }; 199 200 template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name) : 201 TrcPktProcI(component_name), 202 m_config(0), 203 m_b_is_init(false) 204 { 205 } 206 207 template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name, int instIDNum) : 208 TrcPktProcI(component_name, instIDNum), 209 m_config(0), 210 m_b_is_init(false) 211 { 212 } 213 214 template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::~TrcPktProcBase() 215 { 216 ClearConfigObj(); 217 } 218 219 template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::TraceDataIn( const ocsd_datapath_op_t op, 220 const ocsd_trc_index_t index, 221 const uint32_t dataBlockSize, 222 const uint8_t *pDataBlock, 223 uint32_t *numBytesProcessed) 224 { 225 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 226 227 switch(op) 228 { 229 case OCSD_OP_DATA: 230 if((dataBlockSize == 0) || (pDataBlock == 0) || (numBytesProcessed == 0)) 231 { 232 if(numBytesProcessed) 233 *numBytesProcessed = 0; // ensure processed bytes value set to 0. 234 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL,"Packet Processor: Zero length data block or NULL pointer error\n")); 235 resp = OCSD_RESP_FATAL_INVALID_PARAM; 236 } 237 else 238 resp = processData(index,dataBlockSize,pDataBlock,numBytesProcessed); 239 break; 240 241 case OCSD_OP_EOT: 242 resp = EOT(); 243 break; 244 245 case OCSD_OP_FLUSH: 246 resp = Flush(); 247 break; 248 249 case OCSD_OP_RESET: 250 resp = Reset(index); 251 break; 252 253 default: 254 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL,"Packet Processor : Unknown Datapath operation\n")); 255 resp = OCSD_RESP_FATAL_INVALID_OP; 256 break; 257 } 258 return resp; 259 } 260 261 262 template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Reset(const ocsd_trc_index_t index) 263 { 264 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 265 266 // reset the trace decoder attachment on main data path. 267 if(m_pkt_out_i.hasAttachedAndEnabled()) 268 resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_RESET,index,0); 269 270 // reset the packet processor implmentation 271 if(!OCSD_DATA_RESP_IS_FATAL(resp)) 272 resp = onReset(); 273 274 // packet monitor 275 if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) 276 m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_RESET,index,0,0,0); 277 278 return resp; 279 } 280 281 template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Flush() 282 { 283 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 284 ocsd_datapath_resp_t resplocal = OCSD_RESP_CONT; 285 286 // the trace decoder attachment on main data path. 287 if(m_pkt_out_i.hasAttachedAndEnabled()) 288 resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_FLUSH,0,0); // flush up the data path first. 289 290 // if the connected components are flushed, not flush this one. 291 if(OCSD_DATA_RESP_IS_CONT(resp)) 292 resplocal = onFlush(); // local flush 293 294 return (resplocal > resp) ? resplocal : resp; 295 } 296 297 template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::EOT() 298 { 299 ocsd_datapath_resp_t resp = onEOT(); // local EOT - mark any part packet as incomplete type and prepare to send 300 301 // the trace decoder attachment on main data path. 302 if(m_pkt_out_i.hasAttachedAndEnabled() && !OCSD_DATA_RESP_IS_FATAL(resp)) 303 resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_EOT,0,0); 304 305 // packet monitor 306 if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) 307 m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_EOT,0,0,0,0); 308 309 return resp; 310 } 311 312 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) 313 { 314 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 315 316 // bad packet filter. 317 if((getComponentOpMode() & OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS) && isBadPacket()) 318 return resp; 319 320 // send a complete packet over the primary data path 321 if(m_pkt_out_i.hasAttachedAndEnabled()) 322 resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_DATA,index,pkt); 323 return resp; 324 } 325 326 template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::outputRawPacketToMonitor( 327 const ocsd_trc_index_t index_sop, 328 const P *pkt, 329 const uint32_t size, 330 const uint8_t *p_data) 331 { 332 // never output 0 sized packets. 333 if(size == 0) 334 return; 335 336 // bad packet filter. 337 if((getComponentOpMode() & OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS) && isBadPacket()) 338 return; 339 340 // packet monitor - this cannot return CONT / WAIT, but does get the raw packet data. 341 if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) 342 m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_DATA,index_sop,pkt,size,p_data); 343 } 344 345 template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::hasRawMon() const 346 { 347 return m_pkt_raw_mon_i.hasAttachedAndEnabled(); 348 } 349 350 template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::indexPacket(const ocsd_trc_index_t index_sop, const Pt *packet_type) 351 { 352 // packet indexer - cannot return CONT / WAIT, just gets the current index and type. 353 if(m_pkt_indexer_i.hasAttachedAndEnabled()) 354 m_pkt_indexer_i.first()->TracePktIndex(index_sop,packet_type); 355 } 356 357 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) 358 { 359 indexPacket(index_sop,pkt_type); 360 if(pktdata.size() > 0) // prevent out of range errors for 0 length vector. 361 outputRawPacketToMonitor(index_sop,pkt,(uint32_t)pktdata.size(),&pktdata[0]); 362 return outputDecodedPacket(index_sop,pkt); 363 } 364 365 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) 366 { 367 indexPacket(index_sop,pkt_type); 368 outputRawPacketToMonitor(index_sop,pkt,pktlen,pktdata); 369 return outputDecodedPacket(index_sop,pkt); 370 } 371 372 template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::setProtocolConfig(const Pc *config) 373 { 374 ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL; 375 if(config != 0) 376 { 377 ClearConfigObj(); 378 m_config = new (std::nothrow) Pc(*config); 379 if(m_config != 0) 380 err = onProtocolConfig(); 381 else 382 err = OCSD_ERR_MEM; 383 } 384 return err; 385 } 386 387 template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::ClearConfigObj() 388 { 389 if(m_config) 390 { 391 delete m_config; 392 m_config = 0; 393 } 394 } 395 396 template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::checkInit() 397 { 398 if(!m_b_is_init) 399 { 400 if( (m_config != 0) && 401 (m_pkt_out_i.hasAttached() || m_pkt_raw_mon_i.hasAttached()) 402 ) 403 m_b_is_init = true; 404 } 405 return m_b_is_init; 406 } 407 408 /** @}*/ 409 410 #endif // ARM_TRC_PKT_PROC_BASE_H_INCLUDED 411 412 /* End of File trc_pkt_proc_base.h */ 413