traffic-control: PfifoFastQueueDisc uses priority to map packets to bands

This commit is contained in:
Stefano Avallone
2016-07-14 15:59:56 +02:00
parent 1090f53d2f
commit 1ec310b39e
16 changed files with 114 additions and 531 deletions

View File

@@ -306,8 +306,7 @@ int main (int argc, char *argv[])
stack.InstallAll ();
TrafficControlHelper tchPfifo;
uint32_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
TrafficControlHelper tchCoDel;
tchCoDel.SetRootQueueDisc ("ns3::CoDelQueueDisc");

View File

@@ -58,136 +58,4 @@ Ipv4PacketFilter::CheckProtocol (Ptr<QueueDiscItem> item) const
return (DynamicCast<Ipv4QueueDiscItem> (item) != 0);
}
// ------------------------------------------------------------------------- //
NS_OBJECT_ENSURE_REGISTERED (PfifoFastIpv4PacketFilter);
TypeId
PfifoFastIpv4PacketFilter::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::PfifoFastIpv4PacketFilter")
.SetParent<Ipv4PacketFilter> ()
.SetGroupName ("Internet")
.AddConstructor<PfifoFastIpv4PacketFilter> ()
.AddAttribute ("Mode",
"Whether to interpret the TOS byte as legacy TOS or DSCP",
EnumValue (PF_MODE_DSCP),
MakeEnumAccessor (&PfifoFastIpv4PacketFilter::m_trafficClassMode),
MakeEnumChecker (PF_MODE_TOS, "TOS semantics",
PF_MODE_DSCP, "DSCP semantics"))
;
return tid;
}
PfifoFastIpv4PacketFilter::PfifoFastIpv4PacketFilter ()
{
NS_LOG_FUNCTION (this);
}
PfifoFastIpv4PacketFilter::~PfifoFastIpv4PacketFilter()
{
NS_LOG_FUNCTION (this);
}
int32_t
PfifoFastIpv4PacketFilter::DoClassify (Ptr<QueueDiscItem> item) const
{
NS_LOG_FUNCTION (this << item);
uint32_t band;
Ptr<Ipv4QueueDiscItem> ipv4Item = DynamicCast<Ipv4QueueDiscItem> (item);
NS_ASSERT (ipv4Item != 0);
if (m_trafficClassMode == PF_MODE_TOS)
{
uint8_t tos = ipv4Item->GetHeader ().GetTos ();
band = TosToBand (tos);
NS_LOG_DEBUG ("Found Ipv4 packet; TOS " << (uint8_t) tos << " band " << band);
}
else
{
Ipv4Header::DscpType dscp = ipv4Item->GetHeader ().GetDscp ();
band = DscpToBand (dscp);
NS_LOG_DEBUG ("Found Ipv4 packet; DSCP " << ipv4Item->GetHeader ().DscpTypeToString (dscp) << " band " << band);
}
return band;
}
uint32_t
PfifoFastIpv4PacketFilter::TosToBand (uint8_t tos) const
{
NS_LOG_FUNCTION (this << (uint16_t) tos);
uint32_t band = 1;
switch (tos) {
case 0x10 :
case 0x12 :
case 0x14 :
case 0x16 :
band = 0;
break;
case 0x0 :
case 0x4 :
case 0x6 :
case 0x18 :
case 0x1a :
case 0x1c :
case 0x1e :
band = 1;
break;
case 0x2 :
case 0x8 :
case 0xa :
case 0xc :
case 0xe :
band = 2;
break;
default :
NS_LOG_ERROR ("Invalid TOS " << (uint16_t) tos);
}
return band;
}
uint32_t
PfifoFastIpv4PacketFilter::DscpToBand (Ipv4Header::DscpType dscpType) const
{
NS_LOG_FUNCTION (this);
uint32_t band = 1;
switch (dscpType) {
case Ipv4Header::DSCP_EF :
case Ipv4Header::DSCP_AF13 :
case Ipv4Header::DSCP_AF23 :
case Ipv4Header::DSCP_AF33 :
case Ipv4Header::DSCP_AF43 :
case Ipv4Header::DscpDefault :
case Ipv4Header::DSCP_CS2 :
case Ipv4Header::DSCP_CS3 :
band = 1;
break;
case Ipv4Header::DSCP_AF11 :
case Ipv4Header::DSCP_AF21 :
case Ipv4Header::DSCP_AF31 :
case Ipv4Header::DSCP_AF41 :
case Ipv4Header::DSCP_CS1 :
band = 2;
break;
case Ipv4Header::DSCP_AF12 :
case Ipv4Header::DSCP_AF22 :
case Ipv4Header::DSCP_AF32 :
case Ipv4Header::DSCP_AF42 :
case Ipv4Header::DSCP_CS4 :
case Ipv4Header::DSCP_CS5 :
case Ipv4Header::DSCP_CS6 :
case Ipv4Header::DSCP_CS7 :
band = 0;
break;
default :
band = 1;
}
NS_LOG_DEBUG ("Band returned: " << band);
return band;
}
} // namespace ns3

View File

@@ -50,124 +50,6 @@ private:
virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const = 0;
};
/**
* \ingroup ipv4
* \ingroup traffic-control
*
* PfifoFastIpv4PacketFilter is the filter to be added to the PfifoFast
* queue disc to simulate the behavior of the pfifo_fast Linux queue disc.
*
* Two modes of operation are provided. In PF_MODE_TOS mode, packets are
* classified based on the TOS byte (originally defined by RFC 1349:
* http://www.ietf.org/rfc/rfc1349.txt)
*
* 0 1 2 3 4 5 6 7
* +-----+-----+-----+-----+-----+-----+-----+-----+
* | PRECEDENCE | TOS | MBZ |
* +-----+-----+-----+-----+-----+-----+-----+-----+
*
* where MBZ stands for 'must be zero'.
*
* In the eight-bit legacy TOS byte, there were five lower bits for TOS
* and three upper bits for Precedence. Bit 7 was never used. Bits 6-7
* are now repurposed for ECN. The below TOS values correspond to
* bits 3-7 in the TOS byte (i.e. including MBZ), omitting the precedence
* bits 0-2.
*
* TOS | Bits | Means | Linux Priority | Band
* -----|------|-------------------------|----------------|-----
* 0x0 | 0 | Normal Service | 0 Best Effort | 1
* 0x2 | 1 | Minimize Monetary Cost | 1 Filler | 2
* 0x4 | 2 | Maximize Reliability | 0 Best Effort | 1
* 0x6 | 3 | mmc+mr | 0 Best Effort | 1
* 0x8 | 4 | Maximize Throughput | 2 Bulk | 2
* 0xa | 5 | mmc+mt | 2 Bulk | 2
* 0xc | 6 | mr+mt | 2 Bulk | 2
* 0xe | 7 | mmc+mr+mt | 2 Bulk | 2
* 0x10 | 8 | Minimize Delay | 6 Interactive | 0
* 0x12 | 9 | mmc+md | 6 Interactive | 0
* 0x14 | 10 | mr+md | 6 Interactive | 0
* 0x16 | 11 | mmc+mr+md | 6 Interactive | 0
* 0x18 | 12 | mt+md | 4 Int. Bulk | 1
* 0x1a | 13 | mmc+mt+md | 4 Int. Bulk | 1
* 0x1c | 14 | mr+mt+md | 4 Int. Bulk | 1
* 0x1e | 15 | mmc+mr+mt+md | 4 Int. Bulk | 1
*
* In PF_MODE_TOS, the above values are used to map packets into bands, and
* IP precedence bits are disregarded.
*
* In PF_MODE_DSCP (the default), the following mappings are used.
*
* For DSCP, the following values are recommended for Linux in a patch
* to the netdev mailing list from Jesper Dangaard Brouer <brouer@redhat.com>
* on 15 Sept 2014. CS* values I made up myself.
*
* DSCP | Hex | Means | Linux Priority | Band
* -----|------|----------------------------|----------------|-----
* EF | 0x2E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF11 | 0x0A | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF21 | 0x12 | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF31 | 0x1A | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF41 | 0x22 | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF12 | 0x0C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF22 | 0x14 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF32 | 0x1C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF42 | 0x34 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF13 | 0x0E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF23 | 0x16 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF33 | 0x1E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF43 | 0x26 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* CS0 | 0x00 | TC_PRIO_BESTEFFORT | 0 Best Effort | 1
* CS1 | 0x20 | TC_PRIO_FILLER | 1 Filler | 2
* CS2 | 0x40 | TC_PRIO_BULK | 2 Bulk | 1
* CS3 | 0x60 | TC_PRIO_INTERACTIVE_BULK | 4 Int. Bulk | 1
* CS4 | 0x80 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
* CS5 | 0xA0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
* CS6 | 0xC0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
* CS7 | 0xE0 | TC_PRIO_CONTROL | 8 Control | 0
*
*/
class PfifoFastIpv4PacketFilter: public Ipv4PacketFilter {
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
PfifoFastIpv4PacketFilter ();
virtual ~PfifoFastIpv4PacketFilter ();
/**
* \brief Enumeration of modes of Ipv4 header traffic class semantics
*/
enum Ipv4TrafficClassMode
{
PF_MODE_TOS, //!< use legacy TOS semantics to interpret TOS byte
PF_MODE_DSCP, //!< use DSCP semantics to interpret TOS byte
};
private:
virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const;
/**
* \brief Converts a TOS field value into a priority band.
* \param tos The tos to convert.
* \returns The converted band value.
*/
uint32_t TosToBand (uint8_t tos) const;
/**
* \brief Converts a DSCP field value into a priority band.
* \param dscpType The DSCP to convert.
* \returns The converted band value.
*/
uint32_t DscpToBand (Ipv4Header::DscpType dscpType) const;
Ipv4TrafficClassMode m_trafficClassMode; //!< traffic class mode
};
} // namespace ns3
#endif /* IPV4_PACKET_FILTER */

View File

@@ -58,86 +58,4 @@ Ipv6PacketFilter::CheckProtocol (Ptr<QueueDiscItem> item) const
return (DynamicCast<Ipv6QueueDiscItem> (item) != 0);
}
// ------------------------------------------------------------------------- //
NS_OBJECT_ENSURE_REGISTERED (PfifoFastIpv6PacketFilter);
TypeId
PfifoFastIpv6PacketFilter::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::PfifoFastIpv6PacketFilter")
.SetParent<Ipv6PacketFilter> ()
.SetGroupName ("Internet")
.AddConstructor<PfifoFastIpv6PacketFilter> ()
;
return tid;
}
PfifoFastIpv6PacketFilter::PfifoFastIpv6PacketFilter ()
{
NS_LOG_FUNCTION (this);
}
PfifoFastIpv6PacketFilter::~PfifoFastIpv6PacketFilter()
{
NS_LOG_FUNCTION (this);
}
int32_t
PfifoFastIpv6PacketFilter::DoClassify (Ptr<QueueDiscItem> item) const
{
NS_LOG_FUNCTION (this << item);
uint32_t band;
Ptr<Ipv6QueueDiscItem> ipv6Item = DynamicCast<Ipv6QueueDiscItem> (item);
NS_ASSERT (ipv6Item != 0);
Ipv6Header::DscpType dscp = ipv6Item->GetHeader ().GetDscp ();
band = DscpToBand (dscp);
NS_LOG_DEBUG ("Found Ipv6 packet; DSCP " << ipv6Item->GetHeader ().DscpTypeToString (dscp) << " band " << band);
return band;
}
uint32_t
PfifoFastIpv6PacketFilter::DscpToBand (Ipv6Header::DscpType dscpType) const
{
NS_LOG_FUNCTION (this);
uint32_t band = 1;
switch (dscpType) {
case Ipv6Header::DSCP_EF :
case Ipv6Header::DSCP_AF13 :
case Ipv6Header::DSCP_AF23 :
case Ipv6Header::DSCP_AF33 :
case Ipv6Header::DSCP_AF43 :
case Ipv6Header::DscpDefault :
case Ipv6Header::DSCP_CS2 :
case Ipv6Header::DSCP_CS3 :
band = 1;
break;
case Ipv6Header::DSCP_AF11 :
case Ipv6Header::DSCP_AF21 :
case Ipv6Header::DSCP_AF31 :
case Ipv6Header::DSCP_AF41 :
case Ipv6Header::DSCP_CS1 :
band = 2;
break;
case Ipv6Header::DSCP_AF12 :
case Ipv6Header::DSCP_AF22 :
case Ipv6Header::DSCP_AF32 :
case Ipv6Header::DSCP_AF42 :
case Ipv6Header::DSCP_CS4 :
case Ipv6Header::DSCP_CS5 :
case Ipv6Header::DSCP_CS6 :
case Ipv6Header::DSCP_CS7 :
band = 0;
break;
default :
band = 1;
}
NS_LOG_DEBUG ("Band returned: " << band);
return band;
}
} // namespace ns3

View File

@@ -50,66 +50,6 @@ private:
virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const = 0;
};
/**
* \ingroup ipv6
* \ingroup traffic-control
*
* PfifoFastIpv6PacketFilter is the filter to be added to the PfifoFast
* queue disc to simulate the behavior of the pfifo_fast Linux queue disc.
*
* Packets are classified based on the DSCP. The following values are
* recommended for Linux in a patch to the netdev mailing list from
* Jesper Dangaard Brouer <brouer@redhat.com> on 15 Sept 2014.
* CS* values I made up myself.
*
* DSCP | Hex | Means | Linux Priority | Band
* -----|------|----------------------------|----------------|-----
* EF | 0x2E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF11 | 0x0A | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF21 | 0x12 | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF31 | 0x1A | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF41 | 0x22 | TC_PRIO_BULK=2 | 2 Bulk | 2
* AF12 | 0x0C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF22 | 0x14 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF32 | 0x1C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF42 | 0x34 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
* AF13 | 0x0E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF23 | 0x16 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF33 | 0x1E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* AF43 | 0x26 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
* CS0 | 0x00 | TC_PRIO_BESTEFFORT | 0 Best Effort | 1
* CS1 | 0x20 | TC_PRIO_FILLER | 1 Filler | 2
* CS2 | 0x40 | TC_PRIO_BULK | 2 Bulk | 1
* CS3 | 0x60 | TC_PRIO_INTERACTIVE_BULK | 4 Int. Bulk | 1
* CS4 | 0x80 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
* CS5 | 0xA0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
* CS6 | 0xC0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
* CS7 | 0xE0 | TC_PRIO_CONTROL | 8 Control | 0
*
*/
class PfifoFastIpv6PacketFilter: public Ipv6PacketFilter {
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
PfifoFastIpv6PacketFilter ();
virtual ~PfifoFastIpv6PacketFilter ();
private:
virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const;
/**
* \brief Converts a DSCP field value into a priority band.
* \param dscpType The DSCP to convert.
* \returns The converted band value.
*/
uint32_t DscpToBand (Ipv6Header::DscpType dscpType) const;
};
} // namespace ns3
#endif /* IPV6_PACKET_FILTER */

View File

@@ -22,11 +22,11 @@
#include "ns3/drop-tail-queue.h"
#include "ns3/ipv4-queue-disc-item.h"
#include "ns3/ipv6-queue-disc-item.h"
#include "ns3/ipv4-packet-filter.h"
#include "ns3/enum.h"
#include "ns3/uinteger.h"
#include "ns3/pointer.h"
#include "ns3/object-factory.h"
#include "ns3/socket.h"
using namespace ns3;
@@ -41,7 +41,6 @@ public:
private:
virtual void DoRun (void);
Ptr<Packet> CreatePacketWithTos (uint8_t tos);
void TestTosValue (Ptr<PfifoFastQueueDisc> queue, uint8_t tos, uint32_t band);
};
@@ -54,24 +53,17 @@ PfifoFastQueueDiscTosPrioritization::~PfifoFastQueueDiscTosPrioritization ()
{
}
Ptr<Packet>
PfifoFastQueueDiscTosPrioritization::CreatePacketWithTos (uint8_t tos)
void
PfifoFastQueueDiscTosPrioritization::TestTosValue (Ptr<PfifoFastQueueDisc> queue, uint8_t tos, uint32_t band)
{
Ptr<Packet> p = Create<Packet> (100);
Ipv4Header ipHeader;
ipHeader.SetPayloadSize (100);
ipHeader.SetTos (tos);
ipHeader.SetProtocol (6);
p->AddHeader (ipHeader);
return p;
}
void
PfifoFastQueueDiscTosPrioritization::TestTosValue (Ptr<PfifoFastQueueDisc> queue, uint8_t tos, uint32_t band)
{
Ptr<Packet> p = CreatePacketWithTos (tos);
Ipv4Header ipHeader;
p->RemoveHeader (ipHeader);
SocketPriorityTag priorityTag;
priorityTag.SetPriority (Socket::IpTos2Priority (tos));
p->AddPacketTag (priorityTag);
Address dest;
Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHeader);
queue->Enqueue (item);
@@ -84,10 +76,6 @@ void
PfifoFastQueueDiscTosPrioritization::DoRun (void)
{
Ptr<PfifoFastQueueDisc> queueDisc = CreateObject<PfifoFastQueueDisc> ();
Ptr<PfifoFastIpv4PacketFilter> filter = CreateObject<PfifoFastIpv4PacketFilter> ();
bool ok = filter->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastIpv4PacketFilter::PF_MODE_TOS));
NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
queueDisc->AddPacketFilter (filter);
for (uint16_t i = 0; i < 3; i++)
{
Ptr<DropTailQueue> queue = CreateObject<DropTailQueue> ();
@@ -99,22 +87,23 @@ PfifoFastQueueDiscTosPrioritization::DoRun (void)
NS_TEST_ASSERT_MSG_EQ (queueDisc->GetInternalQueue (1)->GetNPackets (), 0, "initialized non-zero");
NS_TEST_ASSERT_MSG_EQ (queueDisc->GetInternalQueue (2)->GetNPackets (), 0, "initialized non-zero");
TestTosValue (queueDisc, 0x0, 1);
TestTosValue (queueDisc, 0x2, 2);
TestTosValue (queueDisc, 0x4, 1);
TestTosValue (queueDisc, 0x6, 1);
TestTosValue (queueDisc, 0x8, 2);
TestTosValue (queueDisc, 0xa, 2);
TestTosValue (queueDisc, 0xc, 2);
TestTosValue (queueDisc, 0xe, 2);
TestTosValue (queueDisc, 0x10, 0);
TestTosValue (queueDisc, 0x12, 0);
TestTosValue (queueDisc, 0x14, 0);
TestTosValue (queueDisc, 0x16, 0);
TestTosValue (queueDisc, 0x18, 1);
TestTosValue (queueDisc, 0x1a, 1);
TestTosValue (queueDisc, 0x1c, 1);
TestTosValue (queueDisc, 0x1e, 1);
// Service name priority band
TestTosValue (queueDisc, 0x00, 1); // Normal service -> Best Effort (0) -> 1
TestTosValue (queueDisc, 0x02, 1); // MMC -> Best Effort (0) -> 1
TestTosValue (queueDisc, 0x04, 1); // MR -> Best Effort (0) -> 1
TestTosValue (queueDisc, 0x06, 1); // MMC+MR -> Best Effort (0) -> 1
TestTosValue (queueDisc, 0x08, 2); // Max. Throughput -> Bulk (2) -> 2
TestTosValue (queueDisc, 0x0a, 2); // MMC+MT -> Bulk (2) -> 2
TestTosValue (queueDisc, 0x0c, 2); // MR+MT -> Bulk (2) -> 2
TestTosValue (queueDisc, 0x0e, 2); // MMC+MR+MT -> Bulk (2) -> 2
TestTosValue (queueDisc, 0x10, 0); // Minimize Delay -> Interactive (6) -> 0
TestTosValue (queueDisc, 0x12, 0); // MMC+MD -> Interactive (6) -> 0
TestTosValue (queueDisc, 0x14, 0); // MR+MD -> Interactive (6) -> 0
TestTosValue (queueDisc, 0x16, 0); // MMC+MR+MD -> Interactive (6) -> 0
TestTosValue (queueDisc, 0x18, 1); // MT+MD -> Int. Bulk (4) -> 1
TestTosValue (queueDisc, 0x1a, 1); // MMC+MT+MD -> Int. Bulk (4) -> 1
TestTosValue (queueDisc, 0x1c, 1); // MR+MT+MD -> Int. Bulk (4) -> 1
TestTosValue (queueDisc, 0x1e, 1); // MMC+MR+MT+MD -> Int. Bulk (4) -> 1
}
/**
@@ -128,7 +117,6 @@ public:
private:
virtual void DoRun (void);
Ptr<Packet> CreatePacketWithDscp (Ipv4Header::DscpType dscp);
void TestDscpValue (Ptr<PfifoFastQueueDisc> queue, Ipv4Header::DscpType dscp, uint32_t band);
};
@@ -141,24 +129,17 @@ PfifoFastQueueDiscDscpPrioritization::~PfifoFastQueueDiscDscpPrioritization ()
{
}
Ptr<Packet>
PfifoFastQueueDiscDscpPrioritization::CreatePacketWithDscp (Ipv4Header::DscpType dscp)
void
PfifoFastQueueDiscDscpPrioritization::TestDscpValue (Ptr<PfifoFastQueueDisc> queue, Ipv4Header::DscpType dscp, uint32_t band)
{
Ptr<Packet> p = Create<Packet> (100);
Ipv4Header ipHeader;
ipHeader.SetPayloadSize (100);
ipHeader.SetProtocol (6);
ipHeader.SetDscp (dscp);
p->AddHeader (ipHeader);
return p;
}
void
PfifoFastQueueDiscDscpPrioritization::TestDscpValue (Ptr<PfifoFastQueueDisc> queue, Ipv4Header::DscpType dscp, uint32_t band)
{
Ptr<Packet> p = CreatePacketWithDscp (dscp);
Ipv4Header ipHeader;
p->RemoveHeader (ipHeader);
SocketPriorityTag priorityTag;
priorityTag.SetPriority (Socket::IpTos2Priority (ipHeader.GetTos ()));
p->AddPacketTag (priorityTag);
Address dest;
Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHeader);
queue->Enqueue (item);
@@ -171,10 +152,6 @@ void
PfifoFastQueueDiscDscpPrioritization::DoRun (void)
{
Ptr<PfifoFastQueueDisc> queueDisc = CreateObject<PfifoFastQueueDisc> ();
Ptr<PfifoFastIpv4PacketFilter> filter = CreateObject<PfifoFastIpv4PacketFilter> ();
bool ok = filter->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastIpv4PacketFilter::PF_MODE_DSCP));
NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
queueDisc->AddPacketFilter (filter);
for (uint16_t i = 0; i < 3; i++)
{
Ptr<DropTailQueue> queue = CreateObject<DropTailQueue> ();
@@ -186,27 +163,28 @@ PfifoFastQueueDiscDscpPrioritization::DoRun (void)
NS_TEST_ASSERT_MSG_EQ (queueDisc->GetInternalQueue (1)->GetNPackets (), 0, "initialized non-zero");
NS_TEST_ASSERT_MSG_EQ (queueDisc->GetInternalQueue (2)->GetNPackets (), 0, "initialized non-zero");
TestDscpValue (queueDisc, Ipv4Header::DscpDefault, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_EF, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF11, 2);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF21, 2);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF31, 2);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF41, 2);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF12, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF22, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF32, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF42, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF13, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF23, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF33, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF43, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS1, 2);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS2, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS3, 1);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS4, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS5, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS6, 0);
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS7, 0);
// priority band
TestDscpValue (queueDisc, Ipv4Header::DscpDefault, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_EF, 1); // Int. Bulk (4) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF11, 2); // Bulk (2) -> 2
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF21, 2); // Bulk (2) -> 2
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF31, 2); // Bulk (2) -> 2
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF41, 2); // Bulk (2) -> 2
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF12, 0); // Interactive (6) -> 0
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF22, 0); // Interactive (6) -> 0
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF32, 0); // Interactive (6) -> 0
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF42, 0); // Interactive (6) -> 0
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF13, 1); // Int. Bulk (4) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF23, 1); // Int. Bulk (4) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF33, 1); // Int. Bulk (4) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_AF43, 1); // Int. Bulk (4) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS1, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS2, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS3, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS4, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS5, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS6, 1); // Best Effort (0) -> 1
TestDscpValue (queueDisc, Ipv4Header::DSCP_CS7, 1); // Best Effort (0) -> 1
}
/**
@@ -240,6 +218,9 @@ PfifoFastQueueDiscOverflow::AddPacket (Ptr<PfifoFastQueueDisc> queue, Ipv4Header
ipHeader.SetPayloadSize (100);
ipHeader.SetProtocol (6);
ipHeader.SetDscp (dscp);
SocketPriorityTag priorityTag;
priorityTag.SetPriority (Socket::IpTos2Priority (ipHeader.GetTos ()));
p->AddPacketTag (priorityTag);
Address dest;
Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHeader);
queue->Enqueue (item);
@@ -255,10 +236,6 @@ PfifoFastQueueDiscOverflow::DoRun (void)
queueDisc->AddInternalQueue (band0);
queueDisc->AddInternalQueue (band1);
queueDisc->AddInternalQueue (band2);
Ptr<PfifoFastIpv4PacketFilter> filter = CreateObject<PfifoFastIpv4PacketFilter> ();
bool ok = filter->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastIpv4PacketFilter::PF_MODE_DSCP));
NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
queueDisc->AddPacketFilter (filter);
// Add two packets per each band
AddPacket (queueDisc, Ipv4Header::DSCP_AF42); // 0
@@ -283,35 +260,33 @@ PfifoFastQueueDiscOverflow::DoRun (void)
}
/**
* This class tests that non-IP packets are handled by placing them into
* band 1
* This class tests that packets without a priority tag are handled by placing
* them into band 1
*/
class PfifoFastQueueDiscNonIpHeader : public TestCase
class PfifoFastQueueDiscNoPriority : public TestCase
{
public:
PfifoFastQueueDiscNonIpHeader ();
virtual ~PfifoFastQueueDiscNonIpHeader ();
PfifoFastQueueDiscNoPriority ();
virtual ~PfifoFastQueueDiscNoPriority ();
private:
virtual void DoRun (void);
};
PfifoFastQueueDiscNonIpHeader::PfifoFastQueueDiscNonIpHeader ()
: TestCase ("Test queue with non IP header")
PfifoFastQueueDiscNoPriority::PfifoFastQueueDiscNoPriority ()
: TestCase ("Test queue with no priority tag")
{
}
PfifoFastQueueDiscNonIpHeader::~PfifoFastQueueDiscNonIpHeader ()
PfifoFastQueueDiscNoPriority::~PfifoFastQueueDiscNoPriority ()
{
}
void
PfifoFastQueueDiscNonIpHeader::DoRun (void)
PfifoFastQueueDiscNoPriority::DoRun (void)
{
// all packets with non-IP headers should enqueue in band 1
Ptr<PfifoFastQueueDisc> queueDisc = CreateObject<PfifoFastQueueDisc> ();
Ptr<PfifoFastIpv4PacketFilter> filter = CreateObject<PfifoFastIpv4PacketFilter> ();
queueDisc->AddPacketFilter (filter);
for (uint16_t i = 0; i < 3; i++)
{
Ptr<DropTailQueue> queue = CreateObject<DropTailQueue> ();
@@ -358,7 +333,7 @@ PfifoFastQueueDiscTestSuite::PfifoFastQueueDiscTestSuite ()
AddTestCase (new PfifoFastQueueDiscTosPrioritization, TestCase::QUICK);
AddTestCase (new PfifoFastQueueDiscDscpPrioritization, TestCase::QUICK);
AddTestCase (new PfifoFastQueueDiscOverflow, TestCase::QUICK);
AddTestCase (new PfifoFastQueueDiscNonIpHeader, TestCase::QUICK);
AddTestCase (new PfifoFastQueueDiscNoPriority, TestCase::QUICK);
}
static PfifoFastQueueDiscTestSuite pfifoFastQueueTestSuite;

View File

@@ -189,6 +189,8 @@ variants has the same effect. Note that, if some subsequent code tries
to read the Packet data buffer, the fake buffer will be converted to
a real (zeroed) buffer on the spot, and the efficiency will be lost there.
.. _Socket-options:
Socket options
**************

View File

@@ -338,7 +338,6 @@ AdaptiveRedQueueDiscTestCase::RunAdaptiveRedDiscTest (StringValue mode)
TrafficControlHelper tchPfifo;
uint16_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
tchPfifo.AddInternalQueues (handle, 3, "ns3::DropTailQueue", "MaxPackets", UintegerValue (1000));
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
TrafficControlHelper tchRed;
tchRed.SetRootQueueDisc ("ns3::RedQueueDisc", "LinkBandwidth", StringValue (aredLinkDataRate),

View File

@@ -8,9 +8,32 @@ Model Description
*****************
Linux pfifo_fast is the default priority queue enabled on Linux
systems. Packets are enqueued in three FIFO droptail queues according
to three priority bands based on the classification returned by
the configured packet filters.
systems. Packets are enqueued in three priority bands (implemented
as FIFO droptail queues) based on their priority (users can read
:ref:`Socket-options` for details on how to set packet priority).
The four least significant bits of the priority are used to determine
the selected band according to the following table:
============== ======
Priority & 0xf Band
============== ======
0 1
1 2
2 2
3 2
4 1
5 2
6 0
7 0
8 1
9 1
10 1
11 1
12 1
13 1
14 1
15 1
============== ======
The system behaves similar to three ns3::DropTail queues operating
together, in which packets from higher priority bands are always
@@ -22,15 +45,7 @@ plays the same role as txqueuelen in Linux. If no internal queue is
provided, three DropTail queues having each a capacity equal to limit are
created by default. User is allowed to provide queues, but they must be
three, operate in packet mode and each have a capacity not less
than limit.
It is necessary to provide at least one packet filter. To simulate the
Linux behavior, the PfifoFastIpv4PacketFilter and/or the PfifoFastIpv6PacketFilter
shall be provided. These filters classify packets based on their Type of
Service bits or DSCP bits. If the filters are unable to classify a packet,
i.e., they return -1 (PF_NO_MATCH), that packet is enqueued into band 1
(normal service).
than limit. No packet filter can be added to a PfifoFastQueueDisc.
Attributes

View File

@@ -311,7 +311,6 @@ main (int argc, char *argv[])
TrafficControlHelper tchPfifo;
uint16_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
tchPfifo.AddInternalQueues (handle, 3, "ns3::DropTailQueue", "MaxPackets", UintegerValue (1000));
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
TrafficControlHelper tchRed;
tchRed.SetRootQueueDisc ("ns3::RedQueueDisc", "LinkBandwidth", StringValue (aredLinkDataRate),

View File

@@ -343,8 +343,7 @@ int main (int argc, char *argv[])
stack.InstallAll ();
TrafficControlHelper tchPfifo;
uint32_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
TrafficControlHelper tchCoDel;
tchCoDel.SetRootQueueDisc ("ns3::CoDelQueueDisc");

View File

@@ -150,8 +150,7 @@ int main (int argc, char *argv[])
stack.InstallAll ();
TrafficControlHelper tchPfifo;
uint32_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
TrafficControlHelper tchCoDel;
tchCoDel.SetRootQueueDisc ("ns3::CoDelQueueDisc");

View File

@@ -347,7 +347,6 @@ main (int argc, char *argv[])
TrafficControlHelper tchPfifo;
uint16_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
tchPfifo.AddInternalQueues (handle, 3, "ns3::DropTailQueue", "MaxPackets", UintegerValue (1000));
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
TrafficControlHelper tchRed;
tchRed.SetRootQueueDisc ("ns3::RedQueueDisc", "LinkBandwidth", StringValue (redLinkDataRate),

View File

@@ -111,8 +111,6 @@ TrafficControlHelper::Default (void)
TrafficControlHelper helper;
uint16_t handle = helper.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
helper.AddInternalQueues (handle, 3, "ns3::DropTailQueue", "MaxPackets", UintegerValue (1000));
helper.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
helper.AddPacketFilter (handle, "ns3::PfifoFastIpv6PacketFilter");
return helper;
}

View File

@@ -24,6 +24,7 @@
#include "ns3/pointer.h"
#include "ns3/object-factory.h"
#include "ns3/drop-tail-queue.h"
#include "ns3/socket.h"
#include "pfifo-fast-queue-disc.h"
namespace ns3 {
@@ -57,6 +58,8 @@ PfifoFastQueueDisc::~PfifoFastQueueDisc ()
NS_LOG_FUNCTION (this);
}
constexpr int PfifoFastQueueDisc::prio2band[];
bool
PfifoFastQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
{
@@ -69,23 +72,14 @@ PfifoFastQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
return false;
}
uint32_t band;
int32_t ret = Classify (item);
uint8_t priority = 0;
SocketPriorityTag priorityTag;
if (item->GetPacket ()->PeekPacketTag (priorityTag))
{
priority = priorityTag.GetPriority ();
}
if (ret == PacketFilter::PF_NO_MATCH)
{
band = 1;
NS_LOG_DEBUG ("The filter was unable to classify; using default band of " << band);
}
else if (ret < 0 || ret > 2)
{
band = 1;
NS_LOG_DEBUG ("The filter returned an invalid value; using default band of " << band);
}
else
{
band = ret;
}
uint32_t band = prio2band[priority & 0x0f];
bool retval = GetInternalQueue(band)->Enqueue (item);
@@ -147,9 +141,9 @@ PfifoFastQueueDisc::CheckConfig (void)
return false;
}
if (GetNPacketFilters () == 0)
if (GetNPacketFilters () != 0)
{
NS_LOG_ERROR ("PfifoFastQueueDisc needs at least a packet filter");
NS_LOG_ERROR ("PfifoFastQueueDisc needs no packet filter");
return false;
}

View File

@@ -32,8 +32,7 @@ namespace ns3 {
*
* Linux pfifo_fast is the default priority queue enabled on Linux
* systems. Packets are enqueued in three FIFO droptail queues according
* to three priority bands based on the classification returned by
* the configured packet filters.
* to three priority bands based on the packet priority.
*
* The system behaves similar to three ns3::DropTail queues operating
* together, in which packets from higher priority bands are always
@@ -45,14 +44,7 @@ namespace ns3 {
* provided, three DropTail queues having each a capacity equal to limit are
* created by default. User is allowed to provide queues, but they must be
* three, operate in packet mode and each have a capacity not less
* than limit.
*
* It is necessary to provide at least one packet filter. To simulate the
* Linux behavior, the PfifoFastIpv4PacketFilter and/or the PfifoFastIpv6PacketFilter
* shall be provided. These filters classify packets based on their Type of
* Service bits or DSCP bits. If the filters are unable to classify a packet,
* i.e., they return -1 (PF_NO_MATCH), that packet is enqueued into band 1
* (normal service).
* than limit. No packet filter can be provided.
*/
class PfifoFastQueueDisc : public QueueDisc {
public:
@@ -70,6 +62,11 @@ public:
virtual ~PfifoFastQueueDisc();
/*
* Priority to band map
*/
static constexpr int prio2band[] = {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1};
private:
virtual bool DoEnqueue (Ptr<QueueDiscItem> item);
virtual Ptr<QueueDiscItem> DoDequeue (void);