diff --git a/src/devices/csma/csma-net-device.cc b/src/devices/csma/csma-net-device.cc index 2d9d1cb5b..ef1575f4c 100644 --- a/src/devices/csma/csma-net-device.cc +++ b/src/devices/csma/csma-net-device.cc @@ -421,6 +421,10 @@ CsmaNetDevice::AddHeader (Ptr p, Mac48Address source, Mac48Address de header.SetLengthType (lengthType); p->AddHeader (header); + if (Node::ChecksumEnabled ()) + { + trailer.EnableFcs (true); + } trailer.CalcFcs (p); p->AddTrailer (trailer); } @@ -747,6 +751,10 @@ CsmaNetDevice::Receive (Ptr packet, Ptr senderDevice) EthernetTrailer trailer; packet->RemoveTrailer (trailer); + if (Node::ChecksumEnabled ()) + { + trailer.EnableFcs (true); + } trailer.CheckFcs (packet); EthernetHeader header (false); diff --git a/src/node/ethernet-trailer.cc b/src/node/ethernet-trailer.cc index d6ce8ddcf..933b6d5e3 100644 --- a/src/node/ethernet-trailer.cc +++ b/src/node/ethernet-trailer.cc @@ -29,17 +29,10 @@ namespace ns3 { NS_OBJECT_ENSURE_REGISTERED (EthernetTrailer); -bool EthernetTrailer::m_calcFcs = false; - EthernetTrailer::EthernetTrailer () -{ - Init(); -} - -void EthernetTrailer::Init() -{ - m_fcs = 0; -} + : m_calcFcs (false), + m_fcs (0) +{} void EthernetTrailer::EnableFcs (bool enable) @@ -50,21 +43,37 @@ EthernetTrailer::EnableFcs (bool enable) bool EthernetTrailer::CheckFcs (Ptr p) const { + int len = p->GetSize (); + uint8_t *buffer; + uint32_t crc; + if (!m_calcFcs) { return true; - } - else - { - NS_LOG_WARN ("FCS calculation is not yet enabled"); - return false; } + + buffer = new uint8_t[len]; + p->CopyData (buffer, len); + crc = DoCalcFcs (buffer, len); + delete[] buffer; + return (m_fcs == crc); } void EthernetTrailer::CalcFcs (Ptr p) { - NS_LOG_WARN ("FCS calculation is not yet enabled"); + int len = p->GetSize (); + uint8_t *buffer; + + if (!m_calcFcs) + { + return; + } + + buffer = new uint8_t[len]; + p->CopyData (buffer, len); + m_fcs = DoCalcFcs (buffer, len); + delete[] buffer; } void @@ -130,4 +139,23 @@ EthernetTrailer::Deserialize (Buffer::Iterator end) return size; } +// This code is copied from /lib/crc32.c in the linux kernel. +// It assumes little endian ordering. +uint32_t +EthernetTrailer::DoCalcFcs (uint8_t *buffer, size_t len) const +{ + uint32_t crc = 0xffffffff; + int i; + + while (len--) + { + crc ^= *buffer++; + for (i = 0; i < 8; i++) + { + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + } + return ~crc; +} + }; // namespace ns3 diff --git a/src/node/ethernet-trailer.h b/src/node/ethernet-trailer.h index 0508bc651..c988d7f2a 100644 --- a/src/node/ethernet-trailer.h +++ b/src/node/ethernet-trailer.h @@ -22,11 +22,11 @@ #define ETHERNET_TRAILER_H #include "ns3/trailer.h" +#include "ns3/packet.h" #include namespace ns3 { -class Packet; /** * \ingroup node @@ -46,10 +46,10 @@ public: EthernetTrailer (); /** - * \brief Enable or disabled FCS checking and calculations + * \brief Enable or disable FCS checking and calculations * \param enable If true, enables FCS calculations. */ - static void EnableFcs (bool enable); + void EnableFcs (bool enable); /** * \brief Updates the Fcs Field to the correct FCS * \param p Reference to a packet on which the FCS should be @@ -89,19 +89,15 @@ public: virtual void Serialize (Buffer::Iterator end) const; virtual uint32_t Deserialize (Buffer::Iterator end); private: - - /** - * Initializes the trailer parameters during construction. - */ - void Init (void); - /** * Enabled FCS calculations. If false, fcs is set to 0 and checkFCS * returns true. */ - static bool m_calcFcs; + bool m_calcFcs; uint32_t m_fcs; /// Value of the fcs contained in the trailer + uint32_t DoCalcFcs (uint8_t *buffer, size_t len) const; + }; } // namespace ns3