blob: de5c6d12e28cdf890581ecef669d495476b43c91 [file] [log] [blame]
/******************************************************************************
* (C) Copyright 2014 AMIQ Consulting
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NAME: amiq_eth_packet_fcoe.cpp
* PROJECT: amiq_eth
* Description: This file declare the Ethernet Fibre Channel over Ethernet (FCoE) packet.
*******************************************************************************/
#ifndef __AMIQ_ETH_PACKET_FCOE
//protection against multiple includes
#define __AMIQ_ETH_PACKET_FCOE
using namespace std;
//Ethernet Fibre Channel over Ethernet (FCoE) packet
class amiq_eth_packet_fcoe: public amiq_eth_packet_ether_type {
public:
//version
amiq_eth_fcoe_version version;
//reserved bits
amiq_eth_fcoe_reserved_size *fcoe_reserved_before_sof;
//start of frame
amiq_sof_legal sof;
//frame
amiq_eth_fcoe_frame_size fc_frame_size;
amiq_eth_data *fc_frame;
//end of frame
amiq_eth_fcoe_eof eof;
//reserved bits
amiq_eth_fcoe_reserved_size *fcoe_reserved_after_eof;
//Frame Check Sequence
amiq_eth_fcs fcs;
bool use_fcs;
//switch to print lists
bool print_lists;
//constructor
amiq_eth_packet_fcoe() {
ether_type = SC_AMIQ_ETH_FCOE;
fcoe_reserved_before_sof = new amiq_eth_fcoe_reserved_size[AMIQ_ETH_FCOE_RESERVED_BEFORE_SOF_SIZE];
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_BEFORE_SOF_SIZE; index++) {
fcoe_reserved_before_sof[index] = 0;
}
fcoe_reserved_after_eof = new amiq_eth_fcoe_reserved_size[AMIQ_ETH_FCOE_RESERVED_AFTER_EOF_SIZE];
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_AFTER_EOF_SIZE; index++) {
fcoe_reserved_after_eof[index] = 0;
}
use_fcs = 0;
print_lists = false;
}
//destructor
virtual ~amiq_eth_packet_fcoe() {
}
//prints the current class to a given output stream
//@param out - output stream
virtual void do_print(ostream& out) const {
amiq_eth_packet_ether_type::do_print(out);
out << AMIQ_ETH_FIELD_SEPARATOR;
out << "VERSION: " << std::hex << version.to_uint() << AMIQ_ETH_FIELD_SEPARATOR;
if (print_lists) {
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_BEFORE_SOF_SIZE; index++) {
out << "RSVD_B_SOF [" << index << "]" << std::hex << fcoe_reserved_before_sof[index].to_uint() << AMIQ_ETH_FIELD_SEPARATOR;
}
}
out << "SOF: " << std::hex << sof << AMIQ_ETH_FIELD_SEPARATOR;
out << "FC FRAME Size: " << std::hex << fc_frame_size.to_uint() << AMIQ_ETH_FIELD_SEPARATOR;
if (print_lists) {
for (unsigned int index = 0; index < fc_frame_size.to_uint(); index++) {
out << "FC_FRAME [" << index << "]" << std::hex << fc_frame[index].to_uint() << AMIQ_ETH_FIELD_SEPARATOR;
}
}
out << "EOF: " << std::hex << eof << AMIQ_ETH_FIELD_SEPARATOR;
if (print_lists) {
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_AFTER_EOF_SIZE; index++) {
out << "RSVD_A_EOF [" << index << "]" << std::hex << fcoe_reserved_after_eof[index].to_uint() << AMIQ_ETH_FIELD_SEPARATOR;
}
}
out << "FCS: " << std::hex << fcs.to_uint();
}
//pack the entire Ethernet packet
//@param packer - the packer used by this function
virtual void do_pack(amiq_eth_packer& packer) const {
amiq_eth_packet_ether_type::do_pack(packer);
amiq_eth_do_pack(packer, version);
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_BEFORE_SOF_SIZE; index++) {
amiq_eth_do_pack(packer, fcoe_reserved_before_sof[index]);
}
amiq_eth_fcoe_sof local_sof;
local_sof = sof;
amiq_eth_do_pack(packer, local_sof);
amiq_eth_do_pack(packer, fc_frame_size);
for (unsigned int index = 0; index < fc_frame_size.to_uint(); index++) {
amiq_eth_do_pack(packer, fc_frame[index]);
}
amiq_eth_fcoe_eof local_eof;
local_eof = eof;
amiq_eth_do_pack(packer, local_eof);
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_AFTER_EOF_SIZE; index++) {
amiq_eth_do_pack(packer, fcoe_reserved_after_eof[index]);
}
if (use_fcs) {
amiq_eth_do_pack(packer, fcs);
}
}
//unpack the entire Ethernet packet
//@param packer - the packer used by this function
virtual void do_unpack(amiq_eth_packer& packer) {
amiq_eth_packet_ether_type::do_unpack(packer);
amiq_eth_fcoe_reserved_size rsvd;
amiq_eth_do_unpack(packer, version);
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_BEFORE_SOF_SIZE; index++) {
amiq_eth_do_unpack(packer, rsvd);
fcoe_reserved_before_sof[index] = rsvd;
}
amiq_eth_fcoe_sof local_sof;
amiq_eth_do_unpack(packer, local_sof);
sof = amiq_sof_legal(local_sof.to_uint());
amiq_eth_do_unpack(packer, fc_frame_size);
amiq_eth_data fc_frame_item;
fc_frame = new amiq_eth_data[fc_frame_size.to_uint()];
for (unsigned int index = 0; index < fc_frame_size.to_uint(); index++) {
amiq_eth_do_unpack(packer, fc_frame_item);
fc_frame[index] = fc_frame_item;
}
amiq_eth_fcoe_eof local_eof;
amiq_eth_do_unpack(packer, local_eof);
eof = amiq_eof_legal(local_eof.to_uint());
for (unsigned int index = 0; index < AMIQ_ETH_FCOE_RESERVED_AFTER_EOF_SIZE; index++) {
amiq_eth_do_unpack(packer, rsvd);
fcoe_reserved_after_eof[index] = rsvd;
}
if (use_fcs) {
amiq_eth_do_unpack(packer, fcs);
}
}
//function for packing the Ethernet packet into an UVM generic payload class
//@return an instance of the UVM generic payload containing the packed Ethernet packet
virtual tlm_generic_payload * to_generic_payload() const {
tlm_generic_payload * result = (amiq_eth_packet_ether_type::to_generic_payload());
result->set_address(AMIQ_ETH_PACKET_FCOE_CODE);
return result;
}
};
#endif