From 044cba4bbd359c4ec1f14c28d6fbe3067658d975 Mon Sep 17 00:00:00 2001
From: Junling Bu
Date: Tue, 3 Dec 2013 11:25:59 -0800
Subject: [PATCH] base implementation of the IEEE 802.11p standard
---
CHANGES.html | 12 +
RELEASE_NOTES | 10 +
doc/models/Makefile | 1 +
doc/models/source/index.rst | 1 +
src/wave/doc/wave.rst | 311 ++++++++++++++++++
src/wave/examples/wave-simple-80211p.cc | 174 ++++++++++
src/wave/examples/wscript | 6 +
src/wave/helper/wave-mac-helper.cc | 125 +++++++
src/wave/helper/wave-mac-helper.h | 144 +++++++++
src/wave/helper/wifi-80211p-helper.cc | 117 +++++++
src/wave/helper/wifi-80211p-helper.h | 79 +++++
src/wave/model/higher-tx-tag.cc | 104 ++++++
src/wave/model/higher-tx-tag.h | 59 ++++
src/wave/model/ocb-wifi-mac.cc | 372 +++++++++++++++++++++
src/wave/model/ocb-wifi-mac.h | 141 ++++++++
src/wave/model/vendor-specific-action.cc | 346 ++++++++++++++++++++
src/wave/model/vendor-specific-action.h | 191 +++++++++++
src/wave/model/wave-mac-low.cc | 86 +++++
src/wave/model/wave-mac-low.h | 51 +++
src/wave/test/examples-to-run.py | 20 ++
src/wave/test/ocb-test-suite.cc | 396 +++++++++++++++++++++++
src/wave/wscript | 40 +++
src/wifi/helper/nqos-wifi-mac-helper.h | 6 +-
src/wifi/helper/qos-wifi-mac-helper.h | 6 +-
src/wifi/helper/wifi-helper.h | 10 +-
src/wifi/model/edca-txop-n.h | 3 +-
src/wifi/model/mac-low.cc | 16 +-
src/wifi/model/mac-low.h | 4 +-
src/wifi/model/mgt-headers.cc | 6 +-
src/wifi/model/mgt-headers.h | 3 +
src/wifi/model/regular-wifi-mac.h | 44 +--
src/wifi/model/wifi-mac-queue.h | 7 +-
src/wifi/model/wifi-net-device.h | 8 +-
33 files changed, 2842 insertions(+), 57 deletions(-)
create mode 100644 src/wave/doc/wave.rst
create mode 100644 src/wave/examples/wave-simple-80211p.cc
create mode 100644 src/wave/examples/wscript
create mode 100644 src/wave/helper/wave-mac-helper.cc
create mode 100644 src/wave/helper/wave-mac-helper.h
create mode 100644 src/wave/helper/wifi-80211p-helper.cc
create mode 100644 src/wave/helper/wifi-80211p-helper.h
create mode 100644 src/wave/model/higher-tx-tag.cc
create mode 100644 src/wave/model/higher-tx-tag.h
create mode 100644 src/wave/model/ocb-wifi-mac.cc
create mode 100644 src/wave/model/ocb-wifi-mac.h
create mode 100644 src/wave/model/vendor-specific-action.cc
create mode 100644 src/wave/model/vendor-specific-action.h
create mode 100644 src/wave/model/wave-mac-low.cc
create mode 100644 src/wave/model/wave-mac-low.h
create mode 100644 src/wave/test/examples-to-run.py
create mode 100644 src/wave/test/ocb-test-suite.cc
create mode 100644 src/wave/wscript
diff --git a/CHANGES.html b/CHANGES.html
index 3c332cbde..73fc05c40 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -54,6 +54,18 @@ us a note on ns-developers mailing list.
Changes from ns-3.18.1 to ns-3.19
New API:
+
+ - A new wifi extension for vehicular simulation support is available in the
+ src/wave directory. The current code represents an interim capability to
+ realize an IEEE 802.11p-compliant device, but without the WAVE extensions
+ (which are planned for a later patch). The WaveNetDevice modelled herein
+ enforces that a WAVE-compliant physical layer (at 5.9 GHz) is selected, and
+ does not require any association between devices (similar to an adhoc WiFi
+ MAC), but is otherwise similar (at this time) to a WifiNetDevice. WAVE
+ capabililties of switching between control and service channels, or using
+ multiple radios, are not yet modelled.
+
+
Changes to existing API:
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 6dfd70671..d31c44f84 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -22,6 +22,16 @@ Supported platforms
New user-visible features
-------------------------
+- A new wifi extension for vehicular simulation support is available in src/wave
+ directory. The current code represents an interim capability to realize an
+ IEEE 802.11p-compliant device, but without the WAVE extensions (which
+ are planned for a later patch). The WaveNetDevice modelled herein enforces that
+ a WAVE-compliant physical layer (at 5.9 GHz) is selected, and does not require
+ any association between devices (similar to an adhoc WiFi MAC), but is
+ otherwise similar (at this time) to a WifiNetDevice. WAVE capabililties of
+ switching between control and service channels, or using multiple radios, are
+ not yet modelled.
+
Bugs fixed
----------
- Bug 1778 - Implement TapBridge::IsLinkUp() function
diff --git a/doc/models/Makefile b/doc/models/Makefile
index 1c8e51ceb..4b043b850 100644
--- a/doc/models/Makefile
+++ b/doc/models/Makefile
@@ -78,6 +78,7 @@ SOURCES = \
$(SRC)/stats/doc/statistics.rst \
$(SRC)/netanim/doc/animation.rst \
$(SRC)/flow-monitor/doc/flow-monitor.rst \
+ $(SRC)/wave/doc/wave.rst \
# list all model library figure files that need to be copied to
# $SOURCETEMP/figures. For each figure to be included in all
diff --git a/doc/models/source/index.rst b/doc/models/source/index.rst
index a1bd49675..d61491b2a 100644
--- a/doc/models/source/index.rst
+++ b/doc/models/source/index.rst
@@ -45,5 +45,6 @@ This document is written in `reStructuredText WifiMacHelper
+ ^ ^ ^
+ | | |
+ | inherit inherit
+ | | |
+ | QosWifiMacHelper NqosWifiMacHelper
+ | ^ ^
+ | | |
+ inherit inherit inherit
+ | | |
+ Wifi80211pHelper QosWaveMacHelper NqosWaveHelper
+
+Although Wifi80211Helper can use any subclasses inheriting from
+WifiMacHelper, we force users to use subclasses inheriting from
+QosWaveMacHelper or NqosWaveHelper.
+
+Although the functions of WiFi 802.11p device can be achieved by
+WaveNetDevice's ContinuousAccess assignment, Wifi80211pHelper is recommeneded
+if there is no need for multiple channel operation.
+Usage is as follows:
+
+::
+
+ NodeContainer nodes;
+ NetDeviceContainer devices;
+ nodes.Create (2);
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ wifiPhy.SetChannel (wifiChannel.Create ());
+ NqosWave80211pMacHelper wifi80211pMac = NqosWaveMacHelper::Default();
+ Wifi80211pHelper 80211pHelper = Wifi80211pHelper::Default ();
+ devices = 80211pHelper.Install (wifiPhy, wifi80211pMac, nodes);
+
+APIs
+====
+
+The 802.11p device can allow the upper layer to send different information
+over Vendor Specific Action management frames by using different
+OrganizationIdentifier fields to identify differences.
+
+1. already create a Node object and WifiNetDevice object
+2. define an OrganizationIdentifier
+
+::
+
+ uint8_t oi_bytes[5] = {0x00, 0x50, 0xC2, 0x4A, 0x40};
+ OrganizationIdentifier oi(oi_bytes,5);
+
+3. define a Callback for the defined OrganizationIdentifier
+
+::
+
+ VscCallback vsccall = MakeCallback (&VsaExample::GetWsaAndOi, this);
+
+4. OcbWifiMac of 802.11p device registers this identifier and function
+
+::
+
+ Ptr device1 = DynamicCast(nodes.Get (i)->GetDevice (0));
+ Ptr ocb1 = DynamicCast(device->GetMac ());
+ ocb1->AddReceiveVscCallback (oi, vsccall);
+
+5. now one can send management packets over VSA frames
+
+::
+
+ Ptr vsc = Create ();
+ ocb2->SendVsc (vsc, Mac48Address::GetBroadcast (), m_16093oi);
+
+6. then registered callbacks in other devices will be called.
+
+Attributes
+==========
+
+The current classes do not provide any additional attributes beyond those
+in the WiFi module.
+
+Output
+======
+
+The current classes provide output of the same type as WiFi devices;
+namely, ASCII and pcap traces, and logging output. The WAVE logging
+components can be enabled globally via the call to
+
+::
+
+ Wifi80211pHelper::EnableLogComponents ();
+
+
+Advanced Usage
+==============
+
+To be defined.
+
+Examples
+========
+
+A basic example exists called ``wave-simple-80211p.cc``.
+This example shows basic construction of an 802.11p node. Two nodes
+are constructed with 802.11p devices, and by default, one node sends a single
+packet to another node (the number of packets and interval between
+them can be configured by command-line arguments). The example shows
+typical usage of the helper classes for this mode of WiFi.
+
+Troubleshooting
+===============
+
+To be defined.
+
+Validation
+**********
+
+A single test suite named ``wifi-80211p-ocb`` is defined. This test
+case consists of a stationary node and a mobile node. The mobile
+node moves towards the stationary mode, and time points are checked
+at which time the physical layer starts to receive packets (and
+whether the MAC becomes associated, if applicable). The same physical
+experiment is repeated for normal WiFi NetDevices in AP/STA mode, in
+Adhoc mode, and the new OCB mode.
+
diff --git a/src/wave/examples/wave-simple-80211p.cc b/src/wave/examples/wave-simple-80211p.cc
new file mode 100644
index 000000000..27d065d80
--- /dev/null
+++ b/src/wave/examples/wave-simple-80211p.cc
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Author: Junling Bu
+ *
+ */
+/**
+ * This example shows basic construction of an 802.11p node. Two nodes
+ * are constructed with 802.11p devices, and by default, one node sends a single
+ * packet to another node (the number of packets and interval between
+ * them can be configured by command-line arguments). The example shows
+ * typical usage of the helper classes for this mode of WiFi (where "OCB" refers
+ * to "Outside the Context of a BSS")."
+ */
+
+#include "ns3/vector.h"
+#include "ns3/string.h"
+#include "ns3/socket.h"
+#include "ns3/double.h"
+#include "ns3/config.h"
+#include "ns3/log.h"
+#include "ns3/command-line.h"
+#include "ns3/mobility-model.h"
+#include "ns3/yans-wifi-helper.h"
+#include "ns3/position-allocator.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv4-interface-container.h"
+#include
+
+#include "ns3/ocb-wifi-mac.h"
+#include "ns3/wifi-80211p-helper.h"
+#include "ns3/wave-mac-helper.h"
+
+NS_LOG_COMPONENT_DEFINE ("WifiSimpleOcb");
+using namespace ns3;
+
+/*
+ * In WAVE module, there is no net device class named like "Wifi80211pNetDevice",
+ * instead, we need to use Wifi80211pHelper to create an object of
+ * WifiNetDevice class.
+ *
+ * usage:
+ * NodeContainer nodes;
+ * NetDeviceContainer devices;
+ * nodes.Create (2);
+ * YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ * YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ * wifiPhy.SetChannel (wifiChannel.Create ());
+ * NqosWaveMacHelper wifi80211pMac = NqosWave80211pMacHelper::Default();
+ * Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default ();
+ * devices = wifi80211p.Install (wifiPhy, wifi80211pMac, nodes);
+ *
+ * The reason of not providing a 802.11p class is that most of modeling
+ * 802.11p standard has been done in wifi module, so we only need a high
+ * MAC class that enables OCB mode.
+ */
+
+void ReceivePacket (Ptr socket)
+{
+ NS_LOG_UNCOND ("Received one packet!");
+}
+
+static void GenerateTraffic (Ptr socket, uint32_t pktSize,
+ uint32_t pktCount, Time pktInterval )
+{
+ if (pktCount > 0)
+ {
+ socket->Send (Create (pktSize));
+ Simulator::Schedule (pktInterval, &GenerateTraffic,
+ socket, pktSize,pktCount - 1, pktInterval);
+ }
+ else
+ {
+ socket->Close ();
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ std::string phyMode ("OfdmRate6MbpsBW10MHz");
+ uint32_t packetSize = 1000; // bytes
+ uint32_t numPackets = 1;
+ double interval = 1.0; // seconds
+ bool verbose = false;
+
+ CommandLine cmd;
+
+ cmd.AddValue ("phyMode", "Wifi Phy mode", phyMode);
+ cmd.AddValue ("packetSize", "size of application packet sent", packetSize);
+ cmd.AddValue ("numPackets", "number of packets generated", numPackets);
+ cmd.AddValue ("interval", "interval (seconds) between packets", interval);
+ cmd.AddValue ("verbose", "turn on all WifiNetDevice log components", verbose);
+ cmd.Parse (argc, argv);
+ // Convert to time object
+ Time interPacketInterval = Seconds (interval);
+
+
+ NodeContainer c;
+ c.Create (2);
+
+ // The below set of helpers will help us to put together the wifi NICs we want
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ Ptr channel = wifiChannel.Create ();
+ wifiPhy.SetChannel (channel);
+ // ns-3 supports generate a pcap trace
+ wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11);
+
+ NqosWaveMacHelper wifi80211pMac = NqosWaveMacHelper::Default ();
+ Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default ();
+ if (verbose)
+ {
+ wifi80211p.EnableLogComponents (); // Turn on all Wifi 802.11p logging
+ }
+
+ wifi80211p.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
+ "DataMode",StringValue (phyMode),
+ "ControlMode",StringValue (phyMode));
+ NetDeviceContainer devices = wifi80211p.Install (wifiPhy, wifi80211pMac, c);
+
+ MobilityHelper mobility;
+ Ptr positionAlloc = CreateObject ();
+ positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+ positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+ mobility.SetPositionAllocator (positionAlloc);
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (c);
+
+ InternetStackHelper internet;
+ internet.Install (c);
+
+ Ipv4AddressHelper ipv4;
+ NS_LOG_INFO ("Assign IP Addresses.");
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer i = ipv4.Assign (devices);
+
+ TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+ Ptr recvSink = Socket::CreateSocket (c.Get (0), tid);
+ InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
+ recvSink->Bind (local);
+ recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));
+
+ Ptr source = Socket::CreateSocket (c.Get (1), tid);
+ InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), 80);
+ source->SetAllowBroadcast (true);
+ source->Connect (remote);
+
+ Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
+ Seconds (1.0), &GenerateTraffic,
+ source, packetSize, numPackets, interPacketInterval);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
diff --git a/src/wave/examples/wscript b/src/wave/examples/wscript
new file mode 100644
index 000000000..d6d0c5248
--- /dev/null
+++ b/src/wave/examples/wscript
@@ -0,0 +1,6 @@
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_program('wave-simple-80211p',
+ ['core', 'applications', 'mobility', 'network', 'wifi','wave'])
+ obj.source = 'wave-simple-80211p.cc'
diff --git a/src/wave/helper/wave-mac-helper.cc b/src/wave/helper/wave-mac-helper.cc
new file mode 100644
index 000000000..807ecf5c2
--- /dev/null
+++ b/src/wave/helper/wave-mac-helper.cc
@@ -0,0 +1,125 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2009 MIRKO BANCHI
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Author: Mirko Banchi
+ * Author: Junling Bu
+ */
+#include "ns3/wifi-mac.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/boolean.h"
+#include "ns3/string.h"
+#include "wave-mac-helper.h"
+
+namespace ns3 {
+
+NqosWaveMacHelper::NqosWaveMacHelper (void)
+{
+
+}
+NqosWaveMacHelper::~NqosWaveMacHelper (void)
+{
+
+}
+NqosWaveMacHelper
+NqosWaveMacHelper::Default (void)
+{
+ NqosWaveMacHelper helper;
+ // We're making non QoS-enabled Wi-Fi MACs here, so we set the
+ // necessary attribute. I've carefully positioned this here so that
+ // someone who knows what they're doing can override with explicit
+ // attributes.
+ helper.SetType ("ns3::OcbWifiMac", "QosSupported", BooleanValue (false));
+ return helper;
+}
+void
+NqosWaveMacHelper::SetType (std::string type,
+ std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ if (type.compare ("ns3::OcbWifiMac") != 0)
+ {
+ NS_FATAL_ERROR ("QosWaveMacHelper shall set OcbWifiMac");
+ }
+ NqosWifiMacHelper::SetType ("ns3::OcbWifiMac",
+ n0, v0,
+ n1, v1,
+ n2, v2,
+ n3, v3,
+ n4, v4,
+ n5, v5,
+ n6, v6,
+ n7, v7);
+}
+
+/********** QosWifi80211pMacHelper *********/
+QosWaveMacHelper::QosWaveMacHelper ()
+{
+}
+QosWaveMacHelper::~QosWaveMacHelper ()
+{
+}
+QosWaveMacHelper
+QosWaveMacHelper::Default (void)
+{
+ QosWaveMacHelper helper;
+
+ // We're making QoS-enabled Wi-Fi MACs here, so we set the necessary
+ // attribute. I've carefully positioned this here so that someone
+ // who knows what they're doing can override with explicit
+ // attributes.
+ helper.SetType ("ns3::OcbWifiMac", "QosSupported", BooleanValue (true));
+
+ return helper;
+}
+void
+QosWaveMacHelper::SetType (std::string type,
+ std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ if (type.compare ("ns3::OcbWifiMac") != 0)
+ {
+ NS_FATAL_ERROR ("QosWaveMacHelper shall set OcbWifiMac");
+ }
+ QosWifiMacHelper::SetType ("ns3::OcbWifiMac",
+ n0, v0,
+ n1, v1,
+ n2, v2,
+ n3, v3,
+ n4, v4,
+ n5, v5,
+ n6, v6,
+ n7, v7);
+}
+
+} // namespace ns3
diff --git a/src/wave/helper/wave-mac-helper.h b/src/wave/helper/wave-mac-helper.h
new file mode 100644
index 000000000..dffff8487
--- /dev/null
+++ b/src/wave/helper/wave-mac-helper.h
@@ -0,0 +1,144 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2009 MIRKO BANCHI
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Author: Mirko Banchi
+ * Author: Junling Bu
+ */
+#ifndef WAVE_MAC_HELPER_H
+#define WAVE_MAC_HELPER_H
+#include "ns3/qos-wifi-mac-helper.h"
+#include "ns3/nqos-wifi-mac-helper.h"
+
+namespace ns3 {
+
+class NqosWaveMacHelper : public NqosWifiMacHelper
+{
+public:
+ /**
+ * Create a NqosWaveMacHelper to make life easier for people who want to
+ * work with non-QOS Wave MAC layers.
+ */
+ NqosWaveMacHelper (void);
+
+ /**
+ * \internal
+ * Destroy a NqosWaveMacHelper.
+ */
+ virtual ~NqosWaveMacHelper (void);
+ /**
+ * Create a mac helper in a default working state.
+ * i.e., this is an ocb mac by default.
+ */
+ static NqosWaveMacHelper Default (void);
+ /**
+ * \param type the type of ns3::WifiMac to create.
+ * \param n0 the name of the attribute to set
+ * \param v0 the value of the attribute to set
+ * \param n1 the name of the attribute to set
+ * \param v1 the value of the attribute to set
+ * \param n2 the name of the attribute to set
+ * \param v2 the value of the attribute to set
+ * \param n3 the name of the attribute to set
+ * \param v3 the value of the attribute to set
+ * \param n4 the name of the attribute to set
+ * \param v4 the value of the attribute to set
+ * \param n5 the name of the attribute to set
+ * \param v5 the value of the attribute to set
+ * \param n6 the name of the attribute to set
+ * \param v6 the value of the attribute to set
+ * \param n7 the name of the attribute to set
+ * \param v7 the value of the attribute to set
+ *
+ * All the attributes specified in this method should exist
+ * in the requested mac.
+ *
+ * note: Here we require users set type with OcbWifiMac or its
+ * subclass, otherwise it will become error
+ */
+ virtual void SetType (std::string type,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+};
+
+class QosWaveMacHelper : public QosWifiMacHelper
+{
+public:
+ /**
+ * Create a QosWaveMacHelper that is used to make life easier when working
+ * with Wifi 802.11p devices using a QOS MAC layer.
+ */
+ QosWaveMacHelper (void);
+
+ /**
+ * \internal
+ * Destroy a QosWaveMacHelper
+ */
+ virtual ~QosWaveMacHelper (void);
+
+ /**
+ * Create a mac helper in a default working state.
+ */
+ static QosWaveMacHelper Default (void);
+
+ /**
+ * \param type the type of ns3::WifiMac to create.
+ * \param n0 the name of the attribute to set
+ * \param v0 the value of the attribute to set
+ * \param n1 the name of the attribute to set
+ * \param v1 the value of the attribute to set
+ * \param n2 the name of the attribute to set
+ * \param v2 the value of the attribute to set
+ * \param n3 the name of the attribute to set
+ * \param v3 the value of the attribute to set
+ * \param n4 the name of the attribute to set
+ * \param v4 the value of the attribute to set
+ * \param n5 the name of the attribute to set
+ * \param v5 the value of the attribute to set
+ * \param n6 the name of the attribute to set
+ * \param v6 the value of the attribute to set
+ * \param n7 the name of the attribute to set
+ * \param v7 the value of the attribute to set
+ *
+ * All the attributes specified in this method should exist
+ * in the requested mac.
+ *
+ * note: Here we require users set type with OcbWifiMac or its
+ * subclass, otherwise it will become error
+ */
+ virtual void SetType (std::string type,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+};
+
+}
+
+#endif /* WAVE_MAC_HELPER_H */
diff --git a/src/wave/helper/wifi-80211p-helper.cc b/src/wave/helper/wifi-80211p-helper.cc
new file mode 100644
index 000000000..015926cfe
--- /dev/null
+++ b/src/wave/helper/wifi-80211p-helper.cc
@@ -0,0 +1,117 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2009 MIRKO BANCHI
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Author: Mirko Banchi
+ * Author: Junling Bu
+ */
+#include "ns3/string.h"
+#include "ns3/log.h"
+#include
+#include "wave-mac-helper.h"
+#include "wifi-80211p-helper.h"
+
+namespace ns3 {
+
+Wifi80211pHelper::Wifi80211pHelper ()
+{
+}
+
+Wifi80211pHelper::~Wifi80211pHelper ()
+{
+}
+
+Wifi80211pHelper
+Wifi80211pHelper::Default (void)
+{
+ Wifi80211pHelper helper;
+ helper.SetStandard (WIFI_PHY_STANDARD_80211_10MHZ);
+ helper.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
+ "DataMode", StringValue ("OfdmRate6MbpsBW10MHz"),
+ "ControlMode",StringValue ("OfdmRate6MbpsBW10MHz"));
+ return helper;
+}
+
+void
+Wifi80211pHelper::SetStandard (enum WifiPhyStandard standard)
+{
+ if ((standard == WIFI_PHY_STANDARD_80211a) || (standard == WIFI_PHY_STANDARD_80211_10MHZ))
+ {
+ WifiHelper::SetStandard (standard);
+ }
+ else
+ {
+ NS_FATAL_ERROR ("802.11p only use 802.11 standard with 10MHz or 20MHz");
+ }
+}
+
+
+void
+Wifi80211pHelper::EnableLogComponents (void)
+{
+ WifiHelper::EnableLogComponents ();
+
+ LogComponentEnable ("OcbWifiMac", LOG_LEVEL_ALL);
+ LogComponentEnable ("VendorSpecificAction", LOG_LEVEL_ALL);
+}
+
+NetDeviceContainer
+Wifi80211pHelper::Install (const WifiPhyHelper &phyHelper, const WifiMacHelper &macHelper, NodeContainer c) const
+{
+ bool isWaveMacHelper = false;
+ try
+ {
+ const QosWaveMacHelper& qosMac = dynamic_cast (macHelper);
+ isWaveMacHelper = true;
+ // below check will never fail, just used for survive from
+ // gcc warn "-Wunused-but-set-variable"
+ if (&qosMac == 0)
+ {
+ NS_FATAL_ERROR ("it could never get here");
+ }
+ }
+ catch (const std::bad_cast &)
+ {
+
+ }
+
+ try
+ {
+ const NqosWaveMacHelper& nqosMac = dynamic_cast (macHelper);
+ isWaveMacHelper = true;
+ if (&nqosMac == 0)
+ {
+ NS_FATAL_ERROR ("it could never get here");
+ }
+ }
+ catch (const std::bad_cast &)
+ {
+
+ }
+
+ if (!isWaveMacHelper)
+ {
+ NS_FATAL_ERROR ("the macHelper should be either QosWaveMacHelper or NqosWaveMacHelper"
+ ", or should be the subclass of QosWaveMacHelper or NqosWaveMacHelper");
+ }
+
+ return WifiHelper::Install (phyHelper, macHelper, c);
+}
+
+} // namespace ns3
diff --git a/src/wave/helper/wifi-80211p-helper.h b/src/wave/helper/wifi-80211p-helper.h
new file mode 100644
index 000000000..d30b55cc7
--- /dev/null
+++ b/src/wave/helper/wifi-80211p-helper.h
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2009 MIRKO BANCHI
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Author: Mirko Banchi
+ * Author: Junling Bu
+ */
+#ifndef WIFI_802_11P_HELPER_H
+#define WIFI_802_11P_HELPER_H
+#include "ns3/wifi-helper.h"
+
+namespace ns3 {
+
+/**
+ * \brief helps to create wifi 802.11p objects of
+ * WifiNetDevice class
+ *
+ * This class can help to create a large set of similar
+ * wifi 802.11p objects and to configure a large set of
+ * their attributes during creation.
+ */
+class Wifi80211pHelper : public WifiHelper
+{
+public:
+ Wifi80211pHelper ();
+ virtual ~Wifi80211pHelper ();
+
+ /**
+ * \returns a new Wifi80211pHelper in a default state
+ *
+ * The default state is defined as being an OcbWifiMac MAC
+ * layer with constant rate OfdmRate6MbpsBW10MHz
+ * and both objects using their default attribute values.
+ */
+ static Wifi80211pHelper Default (void);
+
+ /**
+ * \param standard the phy standard to configure during installation
+ *
+ * Users can only configure 802.11a with 10MHz channel bandwidth indicated by
+ * WIFI_PHY_STANDARD_80211_10MHZ or 20MHz channel bandwidth indicated by
+ * WIFI_PHY_STANDARD_80211a, other standard types will be not allowed.
+ * The default standard is 10MHz.
+ */
+ virtual void SetStandard (enum WifiPhyStandard standard);
+
+ /**
+ * \param phy the PHY helper to create PHY objects
+ * \param mac the MAC helper to create MAC objects
+ * \param c the set of nodes on which a wifi device must be created
+ * \returns a device container which contains all the devices created by this method.
+ */
+ virtual NetDeviceContainer Install (const WifiPhyHelper &phy, const WifiMacHelper &macHelper,NodeContainer c) const;
+
+ /**
+ * Helper to enable all WifiNetDevice log components with one statement
+ */
+ static void EnableLogComponents (void);
+};
+
+}
+
+#endif /* WIFI_802_11P_HELPER_H */
diff --git a/src/wave/model/higher-tx-tag.cc b/src/wave/model/higher-tx-tag.cc
new file mode 100644
index 000000000..53d556660
--- /dev/null
+++ b/src/wave/model/higher-tx-tag.cc
@@ -0,0 +1,104 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Junling Bu
+ */
+#include "higher-tx-tag.h"
+#include "ns3/tag.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+
+NS_LOG_COMPONENT_DEFINE ("HigherDataTxVectorTag");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (HigherDataTxVectorTag);
+
+TypeId
+HigherDataTxVectorTag::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::HigherDataTxVectorTag")
+ .SetParent ()
+ .AddConstructor ()
+ ;
+ return tid;
+}
+HigherDataTxVectorTag::HigherDataTxVectorTag (void)
+ : m_adapter (false)
+{
+ NS_LOG_FUNCTION (this);
+}
+HigherDataTxVectorTag::HigherDataTxVectorTag (WifiTxVector dataTxVector, bool adapter)
+ : m_dataTxVector (dataTxVector),
+ m_adapter (adapter)
+{
+ NS_LOG_FUNCTION (this);
+}
+HigherDataTxVectorTag::~HigherDataTxVectorTag (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+TypeId
+HigherDataTxVectorTag::GetInstanceTypeId (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return GetTypeId ();
+}
+
+WifiTxVector
+HigherDataTxVectorTag::GetDataTxVector (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_dataTxVector;
+}
+bool
+HigherDataTxVectorTag::IsAdapter (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_adapter;
+}
+
+uint32_t
+HigherDataTxVectorTag::GetSerializedSize (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return (sizeof (WifiTxVector) + 1);
+}
+void
+HigherDataTxVectorTag::Serialize (TagBuffer i) const
+{
+ NS_LOG_FUNCTION (this << &i);
+ i.Write ((uint8_t *)&m_dataTxVector, sizeof (WifiTxVector));
+ i.WriteU8 (static_cast (m_adapter));
+}
+void
+HigherDataTxVectorTag::Deserialize (TagBuffer i)
+{
+ NS_LOG_FUNCTION (this << &i);
+ i.Read ((uint8_t *)&m_dataTxVector, sizeof (WifiTxVector));
+ m_adapter = i.ReadU8 ();
+}
+void
+HigherDataTxVectorTag::Print (std::ostream &os) const
+{
+ NS_LOG_FUNCTION (this << &os);
+ os << " Data=" << m_dataTxVector << " Adapter=" << m_adapter;
+}
+
+} // namespace ns3
diff --git a/src/wave/model/higher-tx-tag.h b/src/wave/model/higher-tx-tag.h
new file mode 100644
index 000000000..08cbc93a0
--- /dev/null
+++ b/src/wave/model/higher-tx-tag.h
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Junling Bu
+ */
+#ifndef HIGHER_DATA_TXVECTOR_TAG_H
+#define HIGHER_DATA_TXVECTOR_TAG_H
+
+#include "ns3/packet.h"
+#include "ns3/wifi-tx-vector.h"
+
+namespace ns3 {
+class Tag;
+
+/**
+ * This tag will be used to support higher layer control data rate
+ * and tx power level.
+ */
+class HigherDataTxVectorTag : public Tag
+{
+public:
+ HigherDataTxVectorTag (void);
+ HigherDataTxVectorTag (WifiTxVector dataTxVector, bool adapter);
+ virtual ~HigherDataTxVectorTag (void);
+
+ WifiTxVector GetDataTxVector (void) const;
+ bool IsAdapter (void) const;
+
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (TagBuffer i) const;
+ virtual void Deserialize (TagBuffer i);
+ virtual void Print (std::ostream &os) const;
+
+private:
+ WifiTxVector m_dataTxVector;
+ bool m_adapter;
+};
+
+} // namespace ns3
+
+#endif /* HIGHER_DATA_TXVECTOR_TAG_H*/
diff --git a/src/wave/model/ocb-wifi-mac.cc b/src/wave/model/ocb-wifi-mac.cc
new file mode 100644
index 000000000..1bdbc3c56
--- /dev/null
+++ b/src/wave/model/ocb-wifi-mac.cc
@@ -0,0 +1,372 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Junling Bu
+ */
+#include "ns3/pointer.h"
+#include "ns3/log.h"
+#include "ns3/string.h"
+#include "ns3/qos-tag.h"
+#include "ns3/mac-low.h"
+#include "ns3/dcf-manager.h"
+#include "ns3/mac-rx-middle.h"
+#include "ns3/mgt-headers.h"
+#include "wave-mac-low.h"
+#include "ocb-wifi-mac.h"
+#include "vendor-specific-action.h"
+#include "higher-tx-tag.h"
+
+NS_LOG_COMPONENT_DEFINE ("OcbWifiMac");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (OcbWifiMac);
+
+const static Mac48Address WILDCARD_BSSID = Mac48Address::GetBroadcast ();
+
+TypeId
+OcbWifiMac::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::OcbWifiMac")
+ .SetParent ()
+ .AddConstructor ()
+ ;
+ return tid;
+}
+
+OcbWifiMac::OcbWifiMac (void)
+{
+ NS_LOG_FUNCTION (this);
+
+ // use WaveMacLow instead of MacLow
+ m_low = CreateObject ();
+ m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+ m_dcfManager->SetupLowListener (m_low);
+ m_dca->SetLow (m_low);
+ for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i)
+ {
+ i->second->SetLow (m_low);
+ }
+
+ // Let the lower layers know that we are acting as an OCB node
+ SetTypeOfStation (OCB);
+ // BSSID is still needed in the low part of MAC
+ RegularWifiMac::SetBssid (WILDCARD_BSSID);
+}
+
+OcbWifiMac::~OcbWifiMac (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+OcbWifiMac::SendVsc (Ptr vsc, Mac48Address peer, OrganizationIdentifier oi)
+{
+ NS_LOG_FUNCTION (this << vsc << peer << oi);
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetAddr1 (peer);
+ hdr.SetAddr2 (GetAddress ());
+ hdr.SetAddr3 (WILDCARD_BSSID);
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ VendorSpecificActionHeader vsa;
+ vsa.SetOrganizationIdentifier (oi);
+ vsc->AddHeader (vsa);
+
+ if (m_qosSupported)
+ {
+ uint8_t tid = QosUtilsGetTidForPacket (vsc);
+ tid = tid > 7 ? 0 : tid;
+ m_edca[QosUtilsMapTidToAc (tid)]->Queue (vsc, hdr);
+ }
+ else
+ {
+ m_dca->Queue (vsc, hdr);
+ }
+}
+
+void
+OcbWifiMac::AddReceiveVscCallback (OrganizationIdentifier oi, VscCallback cb)
+{
+ NS_LOG_FUNCTION (this << oi << &cb);
+ m_vscManager.RegisterVscCallback (oi, cb);
+}
+
+void
+OcbWifiMac::RemoveReceiveVscCallback (OrganizationIdentifier oi)
+{
+ NS_LOG_FUNCTION (this << oi);
+ m_vscManager.DeregisterVscCallback (oi);
+}
+
+void
+OcbWifiMac::SetSsid (Ssid ssid)
+{
+ NS_LOG_WARN ("in OCB mode we should not call SetSsid");
+}
+
+Ssid
+OcbWifiMac::GetSsid (void) const
+{
+ NS_FATAL_ERROR ("in OCB mode we should not call GetSsid");
+ // we really do not want to return ssid, however we have to provide
+ return RegularWifiMac::GetSsid ();
+}
+
+
+void
+OcbWifiMac::SetBssid (Mac48Address bssid)
+{
+ NS_FATAL_ERROR ("in OCB mode we should not call SetBsid");
+}
+
+Mac48Address
+OcbWifiMac::GetBssid (void) const
+{
+ NS_FATAL_ERROR ("in OCB mode we should not call GetBssid");
+ return WILDCARD_BSSID;
+}
+
+void
+OcbWifiMac::SetLinkUpCallback (Callback linkUp)
+{
+ NS_LOG_FUNCTION (this << &linkUp);
+ RegularWifiMac::SetLinkUpCallback (linkUp);
+
+ // The approach taken here is that, from the point of view of a STA
+ // in OCB mode, the link is always up, so we immediately invoke the
+ // callback if one is set
+ linkUp ();
+}
+
+void
+OcbWifiMac::SetLinkDownCallback (Callback linkDown)
+{
+ NS_LOG_FUNCTION (this << &linkDown);
+ RegularWifiMac::SetLinkDownCallback (linkDown);
+ NS_LOG_WARN ("in OCB mode the like will never down, so linkDown will never be called");
+}
+
+void
+OcbWifiMac::Enqueue (Ptr packet, Mac48Address to)
+{
+ NS_LOG_FUNCTION (this << packet << to);
+ if (m_stationManager->IsBrandNew (to))
+ {
+ // In ocb mode, we assume that every destination supports all
+ // the rates we support.
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ m_stationManager->AddSupportedMode (to, m_phy->GetMode (i));
+ }
+ m_stationManager->RecordDisassociated (to);
+ }
+
+ WifiMacHeader hdr;
+
+ // If we are not a QoS STA then we definitely want to use AC_BE to
+ // transmit the packet. A TID of zero will map to AC_BE (through \c
+ // QosUtilsMapTidToAc()), so we use that as our default here.
+ uint8_t tid = 0;
+
+ if (m_qosSupported)
+ {
+ hdr.SetType (WIFI_MAC_QOSDATA);
+ hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
+ hdr.SetQosNoEosp ();
+ hdr.SetQosNoAmsdu ();
+ // About transmission of multiple frames,
+ // in Ad-hoc mode TXOP is not supported for now, so TxopLimit=0;
+ // however in OCB mode, 802.11p do not allow transmit multiple frames
+ // so TxopLimit must equal 0
+ hdr.SetQosTxopLimit (0);
+
+ // Fill in the QoS control field in the MAC header
+ tid = QosUtilsGetTidForPacket (packet);
+ // Any value greater than 7 is invalid and likely indicates that
+ // the packet had no QoS tag, so we revert to zero, which'll
+ // mean that AC_BE is used.
+ if (tid >= 7)
+ {
+ tid = 0;
+ }
+ hdr.SetQosTid (tid);
+ }
+ else
+ {
+ hdr.SetTypeData ();
+ }
+
+ hdr.SetAddr1 (to);
+ hdr.SetAddr2 (GetAddress ());
+ hdr.SetAddr3 (WILDCARD_BSSID);
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+
+ if (m_qosSupported)
+ {
+ // Sanity check that the TID is valid
+ NS_ASSERT (tid < 8);
+ m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr);
+ }
+ else
+ {
+ m_dca->Queue (packet, hdr);
+ }
+}
+
+/*
+ * see 802.11p-2010 chapter 11.19
+ * here we only care about data packet and vsa management frame
+ */
+void
+OcbWifiMac::Receive (Ptr packet, const WifiMacHeader *hdr)
+{
+ NS_LOG_FUNCTION (this << packet << hdr);
+ NS_ASSERT (!hdr->IsCtl ());
+ NS_ASSERT (hdr->GetAddr3 () == WILDCARD_BSSID);
+
+ Mac48Address from = hdr->GetAddr2 ();
+ Mac48Address to = hdr->GetAddr1 ();
+
+ if (hdr->IsData ())
+ {
+ if (hdr->IsQosData () && hdr->IsQosAmsdu ())
+ {
+ NS_LOG_DEBUG ("Received A-MSDU from" << from);
+ DeaggregateAmsduAndForward (packet, hdr);
+ }
+ else
+ {
+ ForwardUp (packet, from, to);
+ }
+ return;
+ }
+
+ // why put check here, not before "if (hdr->IsData ())" ?
+ // because WifiNetDevice::ForwardUp needs to m_promiscRx data packet
+ // and will filter data packet for itself
+ // so we need to filter management frame
+ if (to != GetAddress () && !to.IsGroup ())
+ {
+ NS_LOG_LOGIC ("the management frame is not for us");
+ NotifyRxDrop (packet);
+ return;
+ }
+
+ if (hdr->IsMgt () && hdr->IsAction ())
+ {
+ // yes, we only care about VendorSpecificAction frame in OCB mode
+ // other management frames will be handled by RegularWifiMac::Receive
+ VendorSpecificActionHeader vsaHdr;
+ packet->PeekHeader (vsaHdr);
+ if (vsaHdr.GetCategory () == CATEGORY_OF_VSA)
+ {
+ VendorSpecificActionHeader vsa;
+ packet->RemoveHeader (vsa);
+ OrganizationIdentifier oi = vsa.GetOrganizationIdentifier ();
+ VscCallback cb = m_vscManager.FindVscCallback (oi);
+
+ if (cb.IsNull ())
+ {
+ NS_LOG_DEBUG ("cannot find VscCallback for OrganizationIdentifier=" << oi);
+ return;
+ }
+ bool succeed = cb (this, oi,packet, from);
+
+ if (!succeed)
+ {
+ NS_LOG_DEBUG ("vsc callback could not handle the packet successfully");
+ }
+
+ return;
+ }
+ }
+ // Invoke the receive handler of our parent class to deal with any
+ // other frames. Specifically, this will handle Block Ack-related
+ // Management Action frames.
+ RegularWifiMac::Receive (packet, hdr);
+}
+
+void
+OcbWifiMac::ConfigureEdca (uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, enum AcIndex ac)
+{
+ Ptr dcf;
+ switch (ac)
+ {
+ case AC_VO:
+ dcf = RegularWifiMac::GetVOQueue ();
+ dcf->SetMinCw ((cwmin + 1) / 4 - 1);
+ dcf->SetMaxCw ((cwmin + 1) / 2 - 1);
+ dcf->SetAifsn (aifsn);
+ break;
+ case AC_VI:
+ dcf = RegularWifiMac::GetVIQueue ();
+ dcf->SetMinCw ((cwmin + 1) / 2 - 1);
+ dcf->SetMaxCw (cwmin);
+ dcf->SetAifsn (aifsn);
+ break;
+ case AC_BE:
+ dcf = RegularWifiMac::GetBEQueue ();
+ dcf->SetMinCw (cwmin);
+ dcf->SetMaxCw (cwmax);
+ dcf->SetAifsn (aifsn);
+ break;
+ case AC_BK:
+ dcf = RegularWifiMac::GetBKQueue ();
+ dcf->SetMinCw (cwmin);
+ dcf->SetMaxCw (cwmax);
+ dcf->SetAifsn (aifsn);
+ break;
+ case AC_BE_NQOS:
+ dcf = RegularWifiMac::GetDcaTxop ();
+ dcf->SetMinCw (cwmin);
+ dcf->SetMaxCw (cwmax);
+ dcf->SetAifsn (aifsn);
+ break;
+ case AC_UNDEF:
+ NS_FATAL_ERROR ("I don't know what to do with this");
+ break;
+ }
+}
+
+void
+OcbWifiMac::FinishConfigureStandard (enum WifiPhyStandard standard)
+{
+ NS_ASSERT ((standard == WIFI_PHY_STANDARD_80211_10MHZ)
+ || (standard == WIFI_PHY_STANDARD_80211a));
+
+ uint32_t cwmin = 15;
+ uint32_t cwmax = 1023;
+
+ // The special value of AC_BE_NQOS which exists in the Access
+ // Category enumeration allows us to configure plain old DCF.
+ ConfigureEdca (cwmin, cwmax, 2, AC_BE_NQOS);
+
+ // Now we configure the EDCA functions
+ // see IEEE802.11p-2010 section 7.3.2.29
+ // Wave CCH and SCHs set default 802.11p EDCA
+ ConfigureEdca (cwmin, cwmax, 2, AC_VO);
+ ConfigureEdca (cwmin, cwmax, 3, AC_VI);
+ ConfigureEdca (cwmin, cwmax, 6, AC_BE);
+ ConfigureEdca (cwmin, cwmax, 9, AC_BK);
+
+}
+} // namespace ns3
diff --git a/src/wave/model/ocb-wifi-mac.h b/src/wave/model/ocb-wifi-mac.h
new file mode 100644
index 000000000..5d144c69f
--- /dev/null
+++ b/src/wave/model/ocb-wifi-mac.h
@@ -0,0 +1,141 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ * Copyright (c) 2013 Dalian University of Technology
+ *
+ * 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: Mathieu Lacage
+ * Junling Bu
+ */
+#ifndef OCB_WIFI_MAC_H
+#define OCB_WIFI_MAC_H
+
+#include "ns3/object-factory.h"
+#include "ns3/regular-wifi-mac.h"
+#include "ns3/wifi-mac-queue.h"
+#include "ns3/qos-utils.h"
+#include "vendor-specific-action.h"
+
+namespace ns3 {
+class OrganizationIdentifier;
+class WifiMacQueue;
+/**
+ * \brief STAs communicate with each directly outside the context of a BSS
+ * \ingroup wave
+ *
+ * In OCB mac mode,synchronization, association, dis-association
+ * and authentication of normal wifi are not used for wireless access in
+ * vehicular environments.
+ *
+ * Although Timing Advertisement frame is a specific management frame defined
+ * in 802.11p. It is mainly used by IEEE Std 1609.4 for channel switch synchronization.
+ * However in simulation nodes are supposed to have GPS synchronization ability,
+ * so we will not implement this feature.
+ */
+class OcbWifiMac : public RegularWifiMac
+{
+public:
+ static TypeId GetTypeId (void);
+ OcbWifiMac (void);
+ virtual ~OcbWifiMac (void);
+ /**
+ * \param vsc management packet to send.
+ * \param peer the address to which the packet should be sent.
+ * \param oi Organization Identifier field
+ * see 7.3.1.31 Organization Identifier field and 10.3.29 Vendor-specific action
+ *
+ * management information can be transmitted over vender specific action frame.
+ * This will be mainly called by IEEE Std 1609.4 to send WSA from IEEE Std 1609.3
+ */
+ void SendVsc (Ptr vsc, Mac48Address peer, OrganizationIdentifier oi);
+ /**
+ * \param oi Organization Identifier
+ * \param cb callback to invoke whenever a vender specific action frame has been received and must
+ * be forwarded to the higher layers.
+ * every node shall register first if it wants to receive specific vendor specific content.
+ */
+ void AddReceiveVscCallback (OrganizationIdentifier oi, VscCallback cb);
+
+ void RemoveReceiveVscCallback (OrganizationIdentifier oi);
+
+ /**
+ * \returns the ssid which this MAC layer is going to try to stay in.
+ *
+ * This method shall not be used in WAVE environment and
+ * here it will overloaded to log warn message
+ */
+ virtual Ssid GetSsid (void) const;
+ /**
+ * \param ssid the current ssid of this MAC layer.
+ *
+ * This method shall not be used in WAVE environment and
+ * here it will overloaded to log warn message
+ */
+ virtual void SetSsid (Ssid ssid);
+ /**
+ * \param bssid the BSSID of the network that this device belongs to.
+ * This method shall not be used in WAVE environment and
+ * here it will overloaded to log warn message
+ */
+ virtual void SetBssid (Mac48Address bssid);
+ /**
+ * \param bssid the BSSID of the network that this device belongs to.
+ *
+ * This method shall not be used in WAVE environment and
+ * here it will overloaded to log warn message
+ */
+ virtual Mac48Address GetBssid (void) const;
+ /**
+ * SetLinkUpCallback and SetLinkDownCallback will be overloaded
+ * In OCB mode, stations can send packets directly whenever they want
+ * so the link is always up and never down even during channel switch
+ */
+ /**
+ * \param linkUp the callback to invoke when the link becomes up.
+ */
+ virtual void SetLinkUpCallback (Callback linkUp);
+ /**
+ * \param linkDown the callback to invoke when the link becomes down.
+ */
+ virtual void SetLinkDownCallback (Callback linkDown);
+ /**
+ * \param packet the packet to send.
+ * \param to the address to which the packet should be sent.
+ *
+ * The packet should be enqueued in a tx queue, and should be
+ * dequeued as soon as the channel access function determines that
+ * access is granted to this MAC.
+ */
+ virtual void Enqueue (Ptr packet, Mac48Address to);
+ /**
+ * \param cwmin the min contention window
+ * \param cwmax the max contention window
+ * \param aifsn the arbitration inter-frame space
+ * \param ac the access category index
+ *
+ * configure EDCA queue parameters
+ */
+ void ConfigureEdca (uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, enum AcIndex ac);
+
+protected:
+ virtual void FinishConfigureStandard (enum WifiPhyStandard standard);
+private:
+ virtual void Receive (Ptr packet, const WifiMacHeader *hdr);
+
+ VendorSpecificContentManager m_vscManager;
+};
+
+}
+#endif /* OCB_WIFI_MAC_H */
diff --git a/src/wave/model/vendor-specific-action.cc b/src/wave/model/vendor-specific-action.cc
new file mode 100644
index 000000000..ec8d8509a
--- /dev/null
+++ b/src/wave/model/vendor-specific-action.cc
@@ -0,0 +1,346 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 Dalian University of Technology
+ * 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: Junling Bu
+ */
+#include
+#include
+#include
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "vendor-specific-action.h"
+
+NS_LOG_COMPONENT_DEFINE ("VendorSpecificAction");
+
+namespace ns3 {
+
+/*********** OrganizationIdentifier *******/
+
+ATTRIBUTE_HELPER_CPP (OrganizationIdentifier);
+
+OrganizationIdentifier::OrganizationIdentifier (void)
+ : m_type (Unknown)
+{
+ NS_LOG_FUNCTION (this);
+ m_type = Unknown;
+ std::memset (m_oi, 0, 5);
+}
+
+OrganizationIdentifier::OrganizationIdentifier (const uint8_t *str, uint32_t length)
+{
+ NS_LOG_FUNCTION (this << str << length);
+ if (length == 3)
+ {
+ m_type = OUI24;
+ std::memcpy (m_oi, str, length);
+ }
+ else if (length == 5)
+ {
+ m_type = OUI36;
+ std::memcpy (m_oi, str, length);
+ }
+ else
+ {
+ m_type = Unknown;
+ NS_FATAL_ERROR ("cannot support organization identifier with length=" << length);
+ }
+}
+
+OrganizationIdentifier&
+OrganizationIdentifier::operator= (const OrganizationIdentifier& oi)
+{
+ this->m_type = oi.m_type;
+ std::memcpy (this->m_oi, oi.m_oi, 5);
+ return (*this);
+}
+
+OrganizationIdentifier::~OrganizationIdentifier (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+uint8_t
+OrganizationIdentifier::GetManagementId (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_type == OUI36);
+ return (m_oi[4] & 0x0f);
+}
+
+bool
+OrganizationIdentifier::IsNull (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_type == Unknown;
+}
+
+uint32_t
+OrganizationIdentifier::GetSerializedSize (void) const
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_type)
+ {
+ case OUI24:
+ return 3;
+ case OUI36:
+ return 5;
+ case Unknown:
+ default:
+ NS_FATAL_ERROR_NO_MSG ();
+ return 0;
+ }
+}
+
+void
+OrganizationIdentifier::SetType (enum OrganizationIdentifierType type)
+{
+ NS_LOG_FUNCTION (this);
+ m_type = type;
+}
+
+enum OrganizationIdentifier::OrganizationIdentifierType
+OrganizationIdentifier::GetType (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_type;
+}
+
+void
+OrganizationIdentifier::Serialize (Buffer::Iterator start) const
+{
+ NS_LOG_FUNCTION (this << &start);
+ start.Write (m_oi, GetSerializedSize ());
+}
+
+/* because OrganizationIdentifier field is not standard
+ * and the length of OrganizationIdentifier is variable
+ * so data parse here is troublesome
+ */
+uint32_t
+OrganizationIdentifier::Deserialize (Buffer::Iterator start)
+{
+ NS_LOG_FUNCTION (this << &start);
+ // first try to parse OUI24 with 3 bytes
+ start.Read (m_oi, 3);
+ for (std::vector::iterator i = OrganizationIdentifiers.begin (); i != OrganizationIdentifiers.end (); ++i)
+ {
+ if ((i->m_type == OUI24)
+ && (std::memcmp (i->m_oi, m_oi, 3) == 0 ))
+ {
+ m_type = OUI24;
+ return 3;
+ }
+ }
+
+ // then try to parse OUI36 with 5 bytes
+ start.Read (m_oi + 3, 2);
+ for (std::vector::iterator i = OrganizationIdentifiers.begin (); i != OrganizationIdentifiers.end (); ++i)
+ {
+ if ((i->m_type == OUI36)
+ && (std::memcmp (i->m_oi, m_oi, 4) == 0 ))
+ {
+ // OUI36 first check 4 bytes, then check half of the 5th byte
+ if ((i->m_oi[4] & 0xf0) == (m_oi[4] & 0xf0))
+ {
+ m_type = OUI36;
+ return 5;
+ }
+ }
+ }
+
+ // if we cannot deserialize the organization identifier field,
+ // we will fail
+ NS_FATAL_ERROR ("cannot deserialize the organization identifier field successfully");
+ return 0;
+}
+
+bool operator == (const OrganizationIdentifier& a, const OrganizationIdentifier& b)
+{
+ if (a.m_type != b.m_type)
+ {
+ return false;
+ }
+
+ if (a.m_type == OrganizationIdentifier::OUI24)
+ {
+ return memcmp (a.m_oi, b.m_oi, 3) == 0;
+ }
+
+ if (a.m_type == OrganizationIdentifier::OUI36)
+ {
+ return (memcmp (a.m_oi, b.m_oi, 4) == 0)
+ && ((a.m_oi[4] & 0xf0) == (b.m_oi[4] & 0xf0));
+ }
+
+ return false;
+}
+
+bool operator != (const OrganizationIdentifier& a, const OrganizationIdentifier& b)
+{
+ return !(a == b);
+}
+
+bool operator < (const OrganizationIdentifier& a, const OrganizationIdentifier& b)
+{
+ return memcmp (a.m_oi, b.m_oi, std::min (a.m_type, b.m_type)) < 0;
+}
+
+std::ostream& operator << (std::ostream& os, const OrganizationIdentifier& oi)
+{
+ for (uint32_t i = 0; i < oi.m_type; i++)
+ {
+ os << "0x" << std::hex << static_cast (oi.m_oi[i]) << " ";
+ }
+ os << std::endl;
+ return os;
+}
+
+std::istream& operator >> (std::istream& is, const OrganizationIdentifier& oi)
+{
+ return is;
+}
+
+/*********** VendorSpecificActionHeader *******/
+NS_OBJECT_ENSURE_REGISTERED (VendorSpecificActionHeader);
+
+VendorSpecificActionHeader::VendorSpecificActionHeader (void)
+ : m_oi (),
+ m_category (CATEGORY_OF_VSA)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+VendorSpecificActionHeader::~VendorSpecificActionHeader (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+VendorSpecificActionHeader::SetOrganizationIdentifier (OrganizationIdentifier oi)
+{
+ NS_LOG_FUNCTION (this << oi);
+ m_oi = oi;
+}
+
+OrganizationIdentifier
+VendorSpecificActionHeader::GetOrganizationIdentifier (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_oi;
+}
+
+TypeId
+VendorSpecificActionHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::VendorSpecificActionHeader")
+ .SetParent ()
+ .AddConstructor ()
+ ;
+
+ return tid;
+}
+
+uint8_t
+VendorSpecificActionHeader::GetCategory (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_category;
+}
+
+TypeId
+VendorSpecificActionHeader::GetInstanceTypeId (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return GetTypeId ();
+}
+
+void
+VendorSpecificActionHeader::Print (std::ostream &os) const
+{
+ NS_LOG_FUNCTION (this << &os);
+ os << "VendorSpecificActionHeader[ "
+ << "category = 0x" << std::hex << (int)m_category
+ << "organization identifier = " << m_oi
+ << std::dec;
+}
+
+uint32_t
+VendorSpecificActionHeader::GetSerializedSize (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return sizeof(m_category) + m_oi.GetSerializedSize ();
+}
+
+void
+VendorSpecificActionHeader::Serialize (Buffer::Iterator start) const
+{
+ NS_LOG_FUNCTION (this << &start);
+ start.WriteU8 (m_category);
+ m_oi.Serialize (start);
+}
+
+uint32_t
+VendorSpecificActionHeader::Deserialize (Buffer::Iterator start)
+{
+ NS_LOG_FUNCTION (this << &start);
+ m_category = start.ReadU8 ();
+ if (m_category != CATEGORY_OF_VSA)
+ {
+ return 0;
+ }
+ m_oi.Deserialize (start);
+
+ return GetSerializedSize ();
+}
+
+/********* VendorSpecificContentManager ***********/
+VendorSpecificContentManager::VendorSpecificContentManager (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+VendorSpecificContentManager::~VendorSpecificContentManager (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+VendorSpecificContentManager::RegisterVscCallback (OrganizationIdentifier oi, VscCallback cb)
+{
+ NS_LOG_FUNCTION (this << oi << &cb);
+ m_callbacks.insert (std::make_pair (oi, cb));
+ OrganizationIdentifiers.push_back (oi);
+}
+
+void
+VendorSpecificContentManager::DeregisterVscCallback (OrganizationIdentifier &oi)
+{
+ NS_LOG_FUNCTION (this << oi);
+ m_callbacks.erase (oi);
+}
+
+static VscCallback null_callback = MakeNullCallback, const OrganizationIdentifier &,Ptr,const Address &> ();
+
+VscCallback
+VendorSpecificContentManager::FindVscCallback (OrganizationIdentifier &oi)
+{
+ NS_LOG_FUNCTION (this << oi);
+ VscCallbacksI i;
+ i = m_callbacks.find (oi);
+ return (i == m_callbacks.end ()) ? null_callback : i->second;
+}
+
+} // namespace ns3
diff --git a/src/wave/model/vendor-specific-action.h b/src/wave/model/vendor-specific-action.h
new file mode 100644
index 000000000..c6f25e872
--- /dev/null
+++ b/src/wave/model/vendor-specific-action.h
@@ -0,0 +1,191 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 Dalian University of Technology
+ * 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: Junling Bu
+ */
+#ifndef Vendor_Specific_Action_H
+#define Vendor_Specific_Action_H
+
+#include
+#include