wifi: Register a select queue callback

This commit is contained in:
Stefano Avallone
2016-07-14 15:59:55 +02:00
parent 47128c4269
commit b7224c247f
9 changed files with 332 additions and 8 deletions

View File

@@ -0,0 +1,210 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016 Universita' degli Studi di Napoli Federico II
*
* 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: Stefano Avallone <stavallo@unina.it>
*/
#include "ns3/test.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/uinteger.h"
#include "ns3/boolean.h"
#include "ns3/string.h"
#include "ns3/double.h"
#include "ns3/pointer.h"
#include "ns3/ssid.h"
#include "ns3/data-rate.h"
#include "ns3/inet-socket-address.h"
#include "ns3/packet-sink.h"
#include "ns3/wifi-helper.h"
#include "ns3/wifi-net-device.h"
#include "ns3/wifi-mac.h"
#include "ns3/wifi-mac-queue.h"
#include "ns3/edca-txop-n.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/mobility-helper.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/packet-sink-helper.h"
#include "ns3/on-off-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("WifiAcMappingTest");
class WifiAcMappingTest : public TestCase
{
public:
WifiAcMappingTest (uint8_t tos, uint8_t expectedQueue);
virtual void DoRun (void);
private:
uint8_t m_tos;
uint8_t m_expectedQueue;
};
WifiAcMappingTest::WifiAcMappingTest (uint8_t tos, uint8_t expectedQueue)
: TestCase ("User priority to Access Category mapping test"),
m_tos (tos),
m_expectedQueue (expectedQueue)
{
}
void
WifiAcMappingTest::DoRun (void)
{
WifiHelper wifi;
WifiMacHelper wifiMac;
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
wifiPhy.SetChannel (wifiChannel.Create ());
Ssid ssid = Ssid ("wifi-ac-mapping");
wifi.SetRemoteStationManager ("ns3::ArfWifiManager");
// Setup the AP, which will be the source of traffic for this test
NodeContainer ap;
ap.Create (1);
wifiMac.SetType ("ns3::ApWifiMac",
"QosSupported", BooleanValue (true),
"Ssid", SsidValue (ssid));
NetDeviceContainer apDev = wifi.Install (wifiPhy, wifiMac, ap);
// Setup one STA, which will be the sink for traffic in this test.
NodeContainer sta;
sta.Create (1);
wifiMac.SetType ("ns3::StaWifiMac",
"QosSupported", BooleanValue (true),
"Ssid", SsidValue (ssid));
NetDeviceContainer staDev = wifi.Install (wifiPhy, wifiMac, sta);
// Our devices will have fixed positions
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (10.0),
"GridWidth", UintegerValue (2),
"LayoutType", StringValue ("RowFirst"));
mobility.Install (sta);
mobility.Install (ap);
// Now we install internet stacks on our devices
InternetStackHelper stack;
stack.Install (ap);
stack.Install (sta);
Ipv4AddressHelper address;
address.SetBase ("192.168.0.0", "255.255.255.0");
Ipv4InterfaceContainer staNodeInterface, apNodeInterface;
staNodeInterface = address.Assign (staDev);
apNodeInterface = address.Assign (apDev);
uint16_t udpPort = 50000;
PacketSinkHelper packetSink ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), udpPort));
ApplicationContainer sinkApp = packetSink.Install (sta.Get (0));
sinkApp.Start (Seconds (0));
sinkApp.Stop (Seconds (3.0));
// The packet source is an on-off application on the AP device
InetSocketAddress dest (staNodeInterface.GetAddress (0), udpPort);
dest.SetTos (m_tos);
OnOffHelper onoff ("ns3::UdpSocketFactory", dest);
onoff.SetConstantRate (DataRate ("5kbps"), 500);
ApplicationContainer sourceApp = onoff.Install (ap.Get (0));
sourceApp.Start (Seconds (1.0));
sourceApp.Stop (Seconds (3.0));
// The first packet will be transmitted at time 1+(500*8)/5000 = 1.8s.
// Let this packet be transmitted successfully, so that the AP can resolve
// the IP address of the station and get its MAC address.
// The second packet will be transmitted at time 1.8+(500*8)/5000 = 2.6s.
// Put the AP in sleep mode at time 2.0s, so that the second packet remains
// in a wifi mac queue and we can discover the queue it has been sent to.
Ptr<WifiPhy> apPhy = DynamicCast<WifiNetDevice> (apDev.Get (0))->GetPhy ();
Simulator::ScheduleWithContext (ap.Get (0)->GetId (), Seconds (2.0),
&WifiPhy::SetSleepMode, apPhy);
Simulator::Stop (Seconds (4.0));
Ptr<WifiMac> apMac = DynamicCast<WifiNetDevice> (apDev.Get (0))->GetMac ();
PointerValue ptr;
Ptr<WifiMacQueue> queues[4];
// Get the four wifi mac queues and set their MaxDelay attribute to a large
// value, so that packets are not removed by the Cleanup method
apMac->GetAttribute ("BE_EdcaTxopN", ptr);
queues[0] = ptr.Get<EdcaTxopN> ()->GetEdcaQueue ();
queues[0]->SetAttribute ("MaxDelay", TimeValue (Seconds (10.0)));
apMac->GetAttribute ("BK_EdcaTxopN", ptr);
queues[1] = ptr.Get<EdcaTxopN> ()->GetEdcaQueue ();
queues[1]->SetAttribute ("MaxDelay", TimeValue (Seconds (10.0)));
apMac->GetAttribute ("VI_EdcaTxopN", ptr);
queues[2] = ptr.Get<EdcaTxopN> ()->GetEdcaQueue ();
queues[2]->SetAttribute ("MaxDelay", TimeValue (Seconds (10.0)));
apMac->GetAttribute ("VO_EdcaTxopN", ptr);
queues[3] = ptr.Get<EdcaTxopN> ()->GetEdcaQueue ();
queues[3]->SetAttribute ("MaxDelay", TimeValue (Seconds (10.0)));
Simulator::Run ();
for (uint32_t i = 0; i < 4; i++)
{
if (i == m_expectedQueue)
{
NS_TEST_ASSERT_MSG_EQ (queues[i]->GetSize (), 1, "There is no packet in the expected queue " << i);
}
else
{
NS_TEST_ASSERT_MSG_EQ (queues[i]->GetSize (), 0, "Unexpectedly, there is a packet in queue " << i);
}
}
uint32_t totalOctetsThrough =
DynamicCast<PacketSink>(sinkApp.Get (0))->GetTotalRx ();
// Check that the first packet has been received
NS_TEST_ASSERT_MSG_EQ (totalOctetsThrough, 500, "A single packet should have been received");
Simulator::Destroy ();
}
class WifiAcMappingTestSuite : public TestSuite
{
public:
WifiAcMappingTestSuite ();
};
WifiAcMappingTestSuite::WifiAcMappingTestSuite ()
: TestSuite ("ns3-wifi-ac-mapping", SYSTEM)
{
AddTestCase (new WifiAcMappingTest (0xb8, 2), TestCase::QUICK); // EF in AC_VI
AddTestCase (new WifiAcMappingTest (0x28, 1), TestCase::QUICK); // AF11 in AC_BK
AddTestCase (new WifiAcMappingTest (0x70, 0), TestCase::QUICK); // AF32 in AC_BE
AddTestCase (new WifiAcMappingTest (0xc0, 3), TestCase::QUICK); // CS7 in AC_VO
}
static WifiAcMappingTestSuite wifiAcMappingTestSuite;

View File

@@ -41,6 +41,7 @@ def build(bld):
'ns3tcp/ns3tcp-socket-writer.cc',
'ns3wifi/wifi-interference-test-suite.cc',
'ns3wifi/wifi-msdu-aggregator-test-suite.cc',
'ns3wifi/wifi-ac-mapping-test-suite.cc',
'traced/traced-callback-typedef-test-suite.cc',
'traced/traced-value-callback-typedef-test-suite.cc',
]

View File

@@ -26,7 +26,6 @@
#include "ns3/string.h"
#include "ns3/boolean.h"
#include "ns3/trace-source-accessor.h"
#include "qos-tag.h"
#include "mac-low.h"
#include "dcf-manager.h"
#include "mac-rx-middle.h"

View File

@@ -27,7 +27,6 @@
#include "ns3/string.h"
#include "ns3/pointer.h"
#include "ns3/boolean.h"
#include "qos-tag.h"
#include "wifi-phy.h"
#include "dcf-manager.h"
#include "mac-rx-middle.h"

View File

@@ -26,6 +26,7 @@
#include "ns3/tag.h"
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/socket.h"
#include "ns3/double.h"
#include "mac-low.h"
#include "wifi-phy.h"
@@ -741,6 +742,9 @@ MacLow::StartTransmission (Ptr<const Packet> packet,
* one of the Edca of the QAP.
*/
m_currentPacket = packet->Copy ();
// remove the priority tag attached, if any
SocketPriorityTag priorityTag;
m_currentPacket->RemovePacketTag (priorityTag);
m_currentHdr = *hdr;
CancelAllEvents ();
m_listener = listener;

View File

@@ -20,7 +20,7 @@
*/
#include "qos-utils.h"
#include "qos-tag.h"
#include "ns3/socket.h"
namespace ns3 {
@@ -61,13 +61,13 @@ QosUtilsMapTidToAc (uint8_t tid)
uint8_t
QosUtilsGetTidForPacket (Ptr<const Packet> packet)
{
QosTag qos;
SocketPriorityTag qos;
uint8_t tid = 8;
if (packet->PeekPacketTag (qos))
{
if (qos.GetTid () < 8)
if (qos.GetPriority () < 8)
{
tid = qos.GetTid ();
tid = qos.GetPriority ();
}
}
return tid;

View File

@@ -27,7 +27,6 @@
#include "ns3/pointer.h"
#include "ns3/boolean.h"
#include "ns3/trace-source-accessor.h"
#include "qos-tag.h"
#include "mac-low.h"
#include "dcf-manager.h"
#include "mac-rx-middle.h"

View File

@@ -19,12 +19,14 @@
*/
#include "wifi-net-device.h"
#include "wifi-mac.h"
#include "regular-wifi-mac.h"
#include "wifi-phy.h"
#include "wifi-remote-station-manager.h"
#include "wifi-channel.h"
#include "qos-utils.h"
#include "ns3/llc-snap-header.h"
#include "ns3/packet.h"
#include "ns3/socket.h"
#include "ns3/uinteger.h"
#include "ns3/pointer.h"
#include "ns3/node.h"
@@ -94,6 +96,7 @@ WifiNetDevice::DoDispose (void)
m_mac = 0;
m_phy = 0;
m_stationManager = 0;
m_queueInterface = 0;
NetDevice::DoDispose ();
}
@@ -127,6 +130,42 @@ WifiNetDevice::CompleteConfig (void)
m_configComplete = true;
}
void
WifiNetDevice::NotifyNewAggregate (void)
{
NS_LOG_FUNCTION (this);
if (m_queueInterface == 0)
{
Ptr<NetDeviceQueueInterface> ndqi = this->GetObject<NetDeviceQueueInterface> ();
//verify that it's a valid netdevice queue interface and that
//the netdevice queue interface was not set before
if (ndqi != 0)
{
m_queueInterface = ndqi;
if (m_mac == 0)
{
NS_LOG_WARN ("A mac has not been installed yet, using a single tx queue");
}
else
{
Ptr<RegularWifiMac> mac = DynamicCast<RegularWifiMac> (m_mac);
if (mac != 0)
{
BooleanValue qosSupported;
mac->GetAttributeFailSafe ("QosSupported", qosSupported);
if (qosSupported.Get ())
{
m_queueInterface->SetTxQueuesN (4);
// register the select queue callback
m_queueInterface->SetSelectQueueCallback (MakeCallback (&WifiNetDevice::SelectQueue, this));
}
}
}
}
}
NetDevice::NotifyNewAggregate ();
}
void
WifiNetDevice::SetMac (Ptr<WifiMac> mac)
{
@@ -399,4 +438,36 @@ WifiNetDevice::SupportsSendFrom (void) const
return m_mac->SupportsSendFrom ();
}
uint8_t
WifiNetDevice::SelectQueue (Ptr<QueueItem> item) const
{
NS_LOG_FUNCTION (this << item);
NS_ASSERT (m_queueInterface != 0);
if (m_queueInterface->GetTxQueuesN () == 1)
{
return 0;
}
uint8_t dscp, priority = 0;
if (item->GetUint8Value (QueueItem::IP_DSFIELD, dscp))
{
// if the QoS map element is implemented, it should be used here
// to set the priority.
// User priority is set to the three most significant bits of the DS field
priority = dscp >> 5;
}
// replace the priority tag
SocketPriorityTag priorityTag;
priorityTag.SetPriority (priority);
item->GetPacket ()->ReplacePacketTag (priorityTag);
// if the admission control were implemented, here we should check whether
// the access category assigned to the packet should be downgraded
return QosUtilsMapTidToAc (priority);
}
} //namespace ns3

View File

@@ -114,6 +114,7 @@ public:
protected:
virtual void DoDispose (void);
virtual void DoInitialize (void);
virtual void NotifyNewAggregate (void);
/**
* Receive a packet from the lower layer and pass the
* packet up the stack.
@@ -150,10 +151,50 @@ private:
*/
void CompleteConfig (void);
/**
* \brief Determine the tx queue for a given packet
* \param item the packet
*
* Modelled after the Linux function ieee80211_select_queue (net/mac80211/wme.c).
* A SocketPriority tag is attached to the packet (or the existing one is
* replaced) to carry the user priority, which is set to the three most
* significant bits of the DS field (TOS field in case of IPv4 and Traffic
* Class field in case of IPv6). The Access Category corresponding to the
* user priority according to the QosUtilsMapTidToAc function is returned.
*
* The following table shows the mapping for the Diffserv Per Hop Behaviors.
*
* PHB | TOS (binary) | UP | Access Category
* -----|--------------|-----|-----------------
* EF | 101110xx | 5 | AC_VI
* AF11 | 001010xx | 1 | AC_BK
* AF21 | 010010xx | 2 | AC_BK
* AF31 | 011010xx | 3 | AC_BE
* AF41 | 100010xx | 4 | AC_VI
* AF12 | 001100xx | 1 | AC_BK
* AF22 | 010100xx | 2 | AC_BK
* AF32 | 011100xx | 3 | AC_BE
* AF42 | 100100xx | 4 | AC_VI
* AF13 | 001110xx | 1 | AC_BK
* AF23 | 010110xx | 2 | AC_BK
* AF33 | 011110xx | 3 | AC_BE
* AF43 | 100110xx | 4 | AC_VI
* CS0 | 000000xx | 0 | AC_BE
* CS1 | 001000xx | 1 | AC_BK
* CS2 | 010000xx | 2 | AC_BK
* CS3 | 011000xx | 3 | AC_BE
* CS4 | 100000xx | 4 | AC_VI
* CS5 | 101000xx | 5 | AC_VI
* CS6 | 110000xx | 6 | AC_VO
* CS7 | 111000xx | 7 | AC_VO
*/
uint8_t SelectQueue (Ptr<QueueItem> item) const;
Ptr<Node> m_node;
Ptr<WifiPhy> m_phy;
Ptr<WifiMac> m_mac;
Ptr<WifiRemoteStationManager> m_stationManager;
Ptr<NetDeviceQueueInterface> m_queueInterface; //!< NetDevice queue interface
NetDevice::ReceiveCallback m_forwardUp;
NetDevice::PromiscReceiveCallback m_promiscRx;