diff --git a/src/internet/model/arp-header.cc b/src/internet/model/arp-header.cc index 93ca2a0f3..178b67f9d 100644 --- a/src/internet/model/arp-header.cc +++ b/src/internet/model/arp-header.cc @@ -27,6 +27,7 @@ ArpHeader::SetRequest(Address sourceHardwareAddress, { NS_LOG_FUNCTION(this << sourceHardwareAddress << sourceProtocolAddress << destinationHardwareAddress << destinationProtocolAddress); + m_hardwareType = DetermineHardwareType(sourceHardwareAddress); m_type = ARP_TYPE_REQUEST; m_macSource = sourceHardwareAddress; m_macDest = destinationHardwareAddress; @@ -42,6 +43,7 @@ ArpHeader::SetReply(Address sourceHardwareAddress, { NS_LOG_FUNCTION(this << sourceHardwareAddress << sourceProtocolAddress << destinationHardwareAddress << destinationProtocolAddress); + m_hardwareType = DetermineHardwareType(sourceHardwareAddress); m_type = ARP_TYPE_REPLY; m_macSource = sourceHardwareAddress; m_macDest = destinationHardwareAddress; @@ -49,6 +51,22 @@ ArpHeader::SetReply(Address sourceHardwareAddress, m_ipv4Dest = destinationProtocolAddress; } +ArpHeader::HardwareType +ArpHeader::DetermineHardwareType(const Address& address) const +{ + NS_LOG_FUNCTION(this << address); + uint8_t addressLength = address.GetLength(); + switch (addressLength) + { + case 6: + return HardwareType::ETHERNET; + case 8: + return HardwareType::EUI_64; + default: + return HardwareType::UNKNOWN; + } +} + bool ArpHeader::IsRequest() const { @@ -63,6 +81,13 @@ ArpHeader::IsReply() const return m_type == ARP_TYPE_REPLY; } +ArpHeader::HardwareType +ArpHeader::GetHardwareType() const +{ + NS_LOG_FUNCTION(this); + return m_hardwareType; +} + Address ArpHeader::GetSourceHardwareAddress() const { @@ -114,7 +139,8 @@ ArpHeader::Print(std::ostream& os) const NS_LOG_FUNCTION(this << &os); if (IsRequest()) { - os << "request " + os << "hardware type: " << GetHardwareType() << " " + << "request " << "source mac: " << m_macSource << " " << "source ipv4: " << m_ipv4Source << " " << "dest ipv4: " << m_ipv4Dest; @@ -122,7 +148,8 @@ ArpHeader::Print(std::ostream& os) const else { NS_ASSERT(IsReply()); - os << "reply " + os << "hardware type: " << GetHardwareType() << " " + << "reply " << "source mac: " << m_macSource << " " << "source ipv4: " << m_ipv4Source << " " << "dest mac: " << m_macDest << " " @@ -151,8 +178,7 @@ ArpHeader::Serialize(Buffer::Iterator start) const Buffer::Iterator i = start; NS_ASSERT(m_macSource.GetLength() == m_macDest.GetLength()); - /* ethernet */ - i.WriteHtonU16(0x0001); + i.WriteHtonU16(static_cast(m_hardwareType)); /* ipv4 */ i.WriteHtonU16(0x0800); i.WriteU8(m_macSource.GetLength()); @@ -169,10 +195,10 @@ ArpHeader::Deserialize(Buffer::Iterator start) { NS_LOG_FUNCTION(this << &start); Buffer::Iterator i = start; - i.Next(2); // Skip HRD - uint32_t protocolType = i.ReadNtohU16(); // Read PRO - uint32_t hardwareAddressLen = i.ReadU8(); // Read HLN - uint32_t protocolAddressLen = i.ReadU8(); // Read PLN + m_hardwareType = static_cast(i.ReadNtohU16()); // Read HTYPE + uint32_t protocolType = i.ReadNtohU16(); // Read PRO + uint32_t hardwareAddressLen = i.ReadU8(); // Read HLN + uint32_t protocolAddressLen = i.ReadU8(); // Read PLN // // It is implicit here that we have a protocol type of 0x800 (IP). @@ -185,12 +211,27 @@ ArpHeader::Deserialize(Buffer::Iterator start) return 0; } - m_type = i.ReadNtohU16(); // Read OP - ReadFrom(i, m_macSource, hardwareAddressLen); // Read SHA (size HLN) - ReadFrom(i, m_ipv4Source); // Read SPA (size PLN == 4) - ReadFrom(i, m_macDest, hardwareAddressLen); // Read THA (size HLN) - ReadFrom(i, m_ipv4Dest); // Read TPA (size PLN == 4) + m_type = static_cast(i.ReadNtohU16()); // Read OP + ReadFrom(i, m_macSource, hardwareAddressLen); // Read SHA (size HLN) + ReadFrom(i, m_ipv4Source); // Read SPA (size PLN == 4) + ReadFrom(i, m_macDest, hardwareAddressLen); // Read THA (size HLN) + ReadFrom(i, m_ipv4Dest); // Read TPA (size PLN == 4) return GetSerializedSize(); } +std::ostream& +operator<<(std::ostream& os, ArpHeader::HardwareType hardwareType) +{ + switch (hardwareType) + { + case ArpHeader::HardwareType::ETHERNET: + return (os << "Ethernet"); + case ArpHeader::HardwareType::EUI_64: + return (os << "EUI-64"); + case ArpHeader::HardwareType::UNKNOWN: + return (os << "Unknown Hardware Type"); + } + return os << "Unrecognized Hardware Type(" << static_cast(hardwareType) << ")"; +} + } // namespace ns3 diff --git a/src/internet/model/arp-header.h b/src/internet/model/arp-header.h index c0a5eac29..93400cf6a 100644 --- a/src/internet/model/arp-header.h +++ b/src/internet/model/arp-header.h @@ -13,8 +13,6 @@ #include "ns3/header.h" #include "ns3/ipv4-address.h" -#include - namespace ns3 { /** @@ -24,6 +22,33 @@ namespace ns3 class ArpHeader : public Header { public: + /** + * \brief Enumeration listing the possible ARP types + * + * These ARP types are part of the standard ARP packet format as defined in Section + * "Definitions" of \RFC{826}. + */ + enum ArpType_e : uint16_t + { + ARP_TYPE_REQUEST = 1, + ARP_TYPE_REPLY = 2 + }; + + /** + * \brief Enumeration listing the supported hardware types + * + * \RFC{826} specifies that the Hardware Type field in the ARP packet indicates the type + of hardware used. + * For the full list of Hardware Types, refer to: + * https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml + */ + enum class HardwareType : uint16_t + { + UNKNOWN = 0, + ETHERNET = 1, + EUI_64 = 27, + }; + /** * \brief Set the ARP request parameters * \param sourceHardwareAddress the source hardware address @@ -49,6 +74,22 @@ class ArpHeader : public Header Address destinationHardwareAddress, Ipv4Address destinationProtocolAddress); + /** + * @brief Determines the hardware type based on the length of the address. + * + * This method determines the hardware type based on the length of the address. + * It supports two common hardware address lengths: + * - 6 bytes: Assumed to be Ethernet. + * - 8 bytes: Assumed to be EUI-64. + * + * If the length of the address does not match these common lengths, the method defaults + * to Unknown hardware type. + * + * @param address The address whose length is used to determine the hardware type. + * @return The corresponding hardware type. + */ + HardwareType DetermineHardwareType(const Address& address) const; + /** * \brief Check if the ARP is a request * \returns true if it is a request @@ -61,6 +102,12 @@ class ArpHeader : public Header */ bool IsReply() const; + /** + * \brief Get the hardware type + * \return the hardware type + */ + HardwareType GetHardwareType() const; + /** * \brief Returns the source hardware address * \returns the source hardware address @@ -96,22 +143,23 @@ class ArpHeader : public Header void Serialize(Buffer::Iterator start) const override; uint32_t Deserialize(Buffer::Iterator start) override; - /** - * \brief Enumeration listing the possible ARP types - */ - enum ArpType_e - { - ARP_TYPE_REQUEST = 1, - ARP_TYPE_REPLY = 2 - }; - - uint16_t m_type; //!< type of the ICMP (ARP_TYPE_REQUEST) - Address m_macSource; //!< hardware source address - Address m_macDest; //!< hardware destination address - Ipv4Address m_ipv4Source; //!< IP source address - Ipv4Address m_ipv4Dest; //!< IP destination address + HardwareType m_hardwareType; //!< hardware type + ArpType_e m_type; //!< type of the ICMP packet + Address m_macSource; //!< hardware source address + Address m_macDest; //!< hardware destination address + Ipv4Address m_ipv4Source; //!< IP source address + Ipv4Address m_ipv4Dest; //!< IP destination address }; +/** + * \brief Stream insertion operator. + * + * \param os The reference to the output stream + * \param hardwareType the hardware type + * \return The reference to the output stream. + */ +std::ostream& operator<<(std::ostream& os, ArpHeader::HardwareType hardwareType); + } // namespace ns3 #endif /* ARP_HEADER_H */