diff -r 642fa0627ba6 src/internet/model/ipv4-header.cc --- a/src/internet/model/ipv4-header.cc Wed Oct 19 14:25:39 2011 -0400 +++ b/src/internet/model/ipv4-header.cc Thu Oct 20 18:19:06 2011 -0400 @@ -77,6 +77,106 @@ { m_tos = tos; } + +void +Ipv4Header::SetDSCP (DSCPType dscp) +{ + m_tos &= 0x3; // Clear out the DSCP part, retain 2 bits of ECN + m_tos |= dscp; +} + +void +Ipv4Header::SetECN (ECNType ecn) +{ + m_tos &= 0xFC; // Clear out the ECN part, retain 6 bits of DSCP + m_tos |= ecn; +} + +Ipv4Header::DSCPType +Ipv4Header::GetDSCP (void) const +{ + // Extract only first 6 bits of TOS byte, i.e 0xFC + return DSCPType (m_tos & 0xFC); +} + +std::string +Ipv4Header::DSCPTypeToString (DSCPType dscp) const +{ + switch (dscp) + { + case DSCPDefault: + return "Default"; + case CS1: + return "Class Selector 1"; + case AF11: + return "Assured Forwarding 11"; + case AF12: + return "Assured Forwarding 12"; + case AF13: + return "Assured Forwarding 13"; + case CS2: + return "Class Selector 2"; + case AF21: + return "Assured Forwarding 21"; + case AF22: + return "Assured Forwarding 22"; + case AF23: + return "Assured Forwarding 23"; + case CS3: + return "Class Selector 3"; + case AF31: + return "Assured Forwarding 31"; + case AF32: + return "Assured Forwarding 32"; + case AF33: + return "Assured Forwarding 33"; + case CS4: + return "Class Selector 4"; + case AF41: + return "Assured Forwarding 41"; + case AF42: + return "Assured Forwarding 42"; + case AF43: + return "Assured Forwarding 43"; + case CS5: + return "Class Selector 5"; + case EF: + return "Expedited Forwarding"; + case CS6: + return "Class Selector 6"; + case CS7: + return "Class Selector 7"; + default: + return "Unrecognized DSCP"; + }; +} + + +Ipv4Header::ECNType +Ipv4Header::GetECN (void) const +{ + // Extract only last 2 bits of TOS byte, i.e 0x3 + return ECNType (m_tos & 0x3); +} + +std::string +Ipv4Header::ECNTypeToString (ECNType ecn) const +{ + switch (ecn) + { + case NotECT: + return "Not-ECT"; + case ECT1: + return "ECT (1)"; + case ECT0: + return "ECT (0)"; + case CE: + return "CE"; + default: + return "Unknown ECN"; + }; +} + uint8_t Ipv4Header::GetTos (void) const { @@ -224,6 +324,8 @@ flags = "XX"; } os << "tos 0x" << std::hex << m_tos << std::dec << " " + << "DSCP-Type " << DSCPTypeToString (GetDSCP ()) << " " + << "ECN-Type " << ECNTypeToString (GetECN ()) << " " << "ttl " << m_ttl << " " << "id " << m_identification << " " << "protocol " << m_protocol << " " diff -r 642fa0627ba6 src/internet/model/ipv4-header.h --- a/src/internet/model/ipv4-header.h Wed Oct 19 14:25:39 2011 -0400 +++ b/src/internet/model/ipv4-header.h Thu Oct 20 18:19:06 2011 -0400 @@ -54,6 +54,67 @@ */ void SetTos (uint8_t tos); /** + * \enum DSCPType + * \brief DiffServ Code Points + * Code Points defined in + * Assured Forwarding (AF) RFC 2597 + * Expedited Forwarding (EF) RFC 2598 + * Default and Class Selector (CS) RFC 2474 + */ + enum DSCPType + { + DSCPDefault = 0x00, + + CS1 = 0x20, + AF11 = 0x28, + AF12 = 0x30, + AF13 = 0x38, + + CS2 = 0x40, + AF21 = 0x48, + AF22 = 0x50, + AF23 = 0x58, + + CS3 = 0x60, + AF31 = 0x68, + AF32 = 0x70, + AF33 = 0x78, + + CS4 = 0x80, + AF41 = 0x88, + AF42 = 0x90, + AF43 = 0x98, + + CS5 = 0xA0, + EF = 0xB8, + + CS6 = 0xC0, + CS7 = 0xE0 + + }; + /** + * \brief Set DSCP Field + * \param dscp DSCP value + */ + void SetDSCP (DSCPType dscp); + + /** + * \enum ECNType + * \brief ECN Type defined in RFC 3168 + */ + enum ECNType + { + NotECT = 0x00, + ECT1 = 0x01, + ECT0 = 0x02, + CE = 0x03 + }; + /** + * \brief Set ECN Field + * \param ECN Type + */ + void SetECN (ECNType ecn); + /** * This packet is not the last packet of a fragmented ipv4 packet. */ void SetMoreFragments (void); @@ -105,6 +166,22 @@ */ uint8_t GetTos (void) const; /** + * \returns the DSCP field of this packet. + */ + DSCPType GetDSCP (void) const; + /** + * \returns std::string of DSCPType + */ + std::string DSCPTypeToString (DSCPType dscp) const; + /** + * \returns the ECN field of this packet. + */ + ECNType GetECN (void) const; + /** + * \returns std::string of ECNType + */ + std::string ECNTypeToString (ECNType ecn) const; + /** * \returns true if this is the last fragment of a packet, false otherwise. */ bool IsLastFragment (void) const; @@ -158,7 +235,7 @@ uint16_t m_payloadSize; uint16_t m_identification; - uint32_t m_tos : 8; + uint32_t m_tos : 8; //Also used as DSCP + ECN value uint32_t m_ttl : 8; uint32_t m_protocol : 8; uint32_t m_flags : 3; diff -r 642fa0627ba6 src/internet/test/ipv4-header-test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet/test/ipv4-header-test.cc Thu Oct 20 18:19:06 2011 -0400 @@ -0,0 +1,270 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Hajime Tazaki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: John Abraham + * Adapted from: ipv4-raw-test.cc + */ + +#include "ns3/test.h" +#include "ns3/socket-factory.h" +#include "ns3/ipv4-raw-socket-factory.h" +#include "ns3/simulator.h" +#include "ns3/simple-channel.h" +#include "ns3/simple-net-device.h" +#include "ns3/drop-tail-queue.h" +#include "ns3/socket.h" + +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" +#include "ns3/boolean.h" + +#include "ns3/arp-l3-protocol.h" +#include "ns3/ipv4-l3-protocol.h" +#include "ns3/icmpv4-l4-protocol.h" +#include "ns3/ipv4-list-routing.h" +#include "ns3/ipv4-static-routing.h" + +#include +#include +#include +#include +#include +#include +namespace ns3 { + +static void +AddInternetStack (Ptr node) +{ + //ARP + Ptr arp = CreateObject (); + node->AggregateObject (arp); + //IPV4 + Ptr ipv4 = CreateObject (); + //Routing for Ipv4 + Ptr ipv4Routing = CreateObject (); + ipv4->SetRoutingProtocol (ipv4Routing); + Ptr ipv4staticRouting = CreateObject (); + ipv4Routing->AddRoutingProtocol (ipv4staticRouting, 0); + node->AggregateObject (ipv4); + //ICMP + Ptr icmp = CreateObject (); + node->AggregateObject (icmp); + // //Ipv4Raw + // Ptr udp = CreateObject (); + // node->AggregateObject(udp); +} + + +class Ipv4HeaderTest : public TestCase +{ + Ptr m_receivedPacket; + Ipv4Header m_receivedHeader; + void DoSendData_IpHdr_DSCP (Ptr socket, std::string to, Ipv4Header::DSCPType dscp,Ipv4Header::ECNType); + void SendData_IpHdr_DSCP (Ptr socket, std::string to, Ipv4Header::DSCPType dscp, Ipv4Header::ECNType); + +public: + virtual void DoRun (void); + Ipv4HeaderTest (); + + void ReceivePacket (Ptr socket, Ptr packet, const Address &from); + void ReceivePkt (Ptr socket); +}; + + +Ipv4HeaderTest::Ipv4HeaderTest () + : TestCase ("IPv4 Header Test") +{ +} + +void Ipv4HeaderTest::ReceivePacket (Ptr socket, Ptr packet, const Address &from) +{ + m_receivedPacket = packet; +} + + +void Ipv4HeaderTest::ReceivePkt (Ptr socket) +{ + uint32_t availableData; + availableData = socket->GetRxAvailable (); + m_receivedPacket = socket->Recv (2, MSG_PEEK); + NS_ASSERT (m_receivedPacket->GetSize () == 2); + m_receivedPacket = socket->Recv (std::numeric_limits::max (), 0); + NS_ASSERT (availableData == m_receivedPacket->GetSize ()); + //cast availableData to void, to suppress 'availableData' set but not used + //compiler warning + (void) availableData; + m_receivedPacket->PeekHeader (m_receivedHeader); +} + + + +void +Ipv4HeaderTest::DoSendData_IpHdr_DSCP (Ptr socket, std::string to, Ipv4Header::DSCPType dscp, Ipv4Header::ECNType ecn) +{ + Address realTo = InetSocketAddress (Ipv4Address (to.c_str ()), 0); + socket->SetAttribute ("IpHeaderInclude", BooleanValue (true)); + Ptr p = Create (123); + Ipv4Header ipHeader; + ipHeader.SetSource (Ipv4Address ("10.0.0.2")); + ipHeader.SetDestination (Ipv4Address (to.c_str ())); + ipHeader.SetProtocol (0); + ipHeader.SetPayloadSize (p->GetSize ()); + ipHeader.SetTtl (255); + ipHeader.SetDSCP (dscp); + ipHeader.SetECN (ecn); + p->AddHeader (ipHeader); + + NS_TEST_EXPECT_MSG_EQ (socket->SendTo (p, 0, realTo), + 143, to); + socket->SetAttribute ("IpHeaderInclude", BooleanValue (false)); +} + +void +Ipv4HeaderTest::SendData_IpHdr_DSCP (Ptr socket, std::string to, Ipv4Header::DSCPType dscp, Ipv4Header::ECNType ecn) +{ + m_receivedPacket = Create (); + Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0), + &Ipv4HeaderTest::DoSendData_IpHdr_DSCP, this, socket, to, dscp, ecn); + Simulator::Run (); +} + +void +Ipv4HeaderTest::DoRun (void) +{ + // Create topology + + // Receiver Node + Ptr rxNode = CreateObject (); + AddInternetStack (rxNode); + Ptr rxDev1, rxDev2; + { // first interface + rxDev1 = CreateObject (); + rxDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + rxNode->AddDevice (rxDev1); + Ptr ipv4 = rxNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (rxDev1); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); + ipv4->SetUp (netdev_idx); + } + + + // Sender Node + Ptr txNode = CreateObject (); + AddInternetStack (txNode); + Ptr txDev1; + { + txDev1 = CreateObject (); + txDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + txNode->AddDevice (txDev1); + Ptr ipv4 = txNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (txDev1); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); + ipv4->SetUp (netdev_idx); + } + + // link the two nodes + Ptr channel1 = CreateObject (); + rxDev1->SetChannel (channel1); + txDev1->SetChannel (channel1); + + + // Create the IPv4 Raw sockets + Ptr rxSocketFactory = rxNode->GetObject (); + Ptr rxSocket = rxSocketFactory->CreateSocket (); + NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 0)), 0, "trivial"); + rxSocket->SetRecvCallback (MakeCallback (&Ipv4HeaderTest::ReceivePkt, this)); + + + Ptr txSocketFactory = txNode->GetObject (); + Ptr txSocket = txSocketFactory->CreateSocket (); + + // ------ Now the tests ------------ + + // DSCP Tests + std::cout << "DSCP Test\n"; + + std::vector vDSCPTypes; + vDSCPTypes.push_back (Ipv4Header::DSCPDefault); + vDSCPTypes.push_back (Ipv4Header::CS1); + vDSCPTypes.push_back (Ipv4Header::AF11); + vDSCPTypes.push_back (Ipv4Header::AF12); + vDSCPTypes.push_back (Ipv4Header::AF13); + vDSCPTypes.push_back (Ipv4Header::CS2); + vDSCPTypes.push_back (Ipv4Header::AF21); + vDSCPTypes.push_back (Ipv4Header::AF22); + vDSCPTypes.push_back (Ipv4Header::AF23); + vDSCPTypes.push_back (Ipv4Header::CS3); + vDSCPTypes.push_back (Ipv4Header::AF31); + vDSCPTypes.push_back (Ipv4Header::AF32); + vDSCPTypes.push_back (Ipv4Header::AF33); + vDSCPTypes.push_back (Ipv4Header::CS4); + vDSCPTypes.push_back (Ipv4Header::AF41); + vDSCPTypes.push_back (Ipv4Header::AF42); + vDSCPTypes.push_back (Ipv4Header::AF43); + vDSCPTypes.push_back (Ipv4Header::CS5); + vDSCPTypes.push_back (Ipv4Header::EF); + vDSCPTypes.push_back (Ipv4Header::CS6); + vDSCPTypes.push_back (Ipv4Header::CS7); + + for (uint32_t i = 0; i < vDSCPTypes.size (); i++) + { + SendData_IpHdr_DSCP (txSocket, "10.0.0.1", vDSCPTypes [i], Ipv4Header::ECT1); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 143, "recv(hdrincl): 10.0.0.1"); + NS_TEST_EXPECT_MSG_EQ (m_receivedHeader.GetDSCP (), vDSCPTypes [i], "recv(hdrincl): 10.0.0.1"); + m_receivedHeader.Print (std::cout); + std::cout << std::endl; + m_receivedPacket->RemoveAllByteTags (); + m_receivedPacket = 0; + } + + // ECN tests + std::cout << "ECN Test\n"; + std::vector vECNTypes; + vECNTypes.push_back (Ipv4Header::NotECT); + vECNTypes.push_back (Ipv4Header::ECT1); + vECNTypes.push_back (Ipv4Header::ECT0); + vECNTypes.push_back (Ipv4Header::CE); + + for (uint32_t i = 0; i < vECNTypes.size (); i++) + { + SendData_IpHdr_DSCP (txSocket, "10.0.0.1", Ipv4Header::DSCPDefault, vECNTypes [i]); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 143, "recv(hdrincl): 10.0.0.1"); + NS_TEST_EXPECT_MSG_EQ (m_receivedHeader.GetECN (), vECNTypes [i], "recv(hdrincl): 10.0.0.1"); + m_receivedHeader.Print (std::cout); + std::cout << std::endl; + m_receivedPacket->RemoveAllByteTags (); + m_receivedPacket = 0; + } + + + + Simulator::Destroy (); +} +//----------------------------------------------------------------------------- +class Ipv4HeaderTestSuite : public TestSuite +{ +public: + Ipv4HeaderTestSuite () : TestSuite ("ipv4-header", UNIT) + { + AddTestCase (new Ipv4HeaderTest); + } +} g_ipv4HeaderTestSuite; + +} // namespace ns3 diff -r 642fa0627ba6 src/internet/wscript --- a/src/internet/wscript Wed Oct 19 14:25:39 2011 -0400 +++ b/src/internet/wscript Thu Oct 20 18:19:06 2011 -0400 @@ -193,6 +193,7 @@ 'test/ipv4-list-routing-test-suite.cc', 'test/ipv4-packet-info-tag-test-suite.cc', 'test/ipv4-raw-test.cc', + 'test/ipv4-header-test.cc', 'test/ipv4-fragmentation-test.cc', 'test/error-channel.cc', 'test/error-net-device.cc',