404 lines
9.3 KiB
C++
404 lines
9.3 KiB
C++
/*
|
|
* 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 <linlinjavaer@gmail.com>
|
|
*/
|
|
#include "vendor-specific-action.h"
|
|
|
|
#include "ns3/assert.h"
|
|
#include "ns3/log.h"
|
|
|
|
#include <cstring>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
NS_LOG_COMPONENT_DEFINE("VendorSpecificAction");
|
|
|
|
/*********** OrganizationIdentifier *******/
|
|
|
|
ATTRIBUTE_HELPER_CPP(OrganizationIdentifier);
|
|
|
|
OrganizationIdentifier::OrganizationIdentifier()
|
|
: 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()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
}
|
|
|
|
uint8_t
|
|
OrganizationIdentifier::GetManagementId() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
NS_ASSERT(m_type == OUI36);
|
|
return (m_oi[4] & 0x0f);
|
|
}
|
|
|
|
bool
|
|
OrganizationIdentifier::IsNull() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_type == Unknown;
|
|
}
|
|
|
|
uint32_t
|
|
OrganizationIdentifier::GetSerializedSize() 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() 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<OrganizationIdentifier>::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<OrganizationIdentifier>::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;
|
|
}
|
|
|
|
/**
|
|
* equality operator
|
|
* \param a left side object
|
|
* \param b right side object
|
|
* \returns true if equal
|
|
*/
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* inequality operator
|
|
* \param a left side object
|
|
* \param b right side object
|
|
* \returns true if not equal
|
|
*/
|
|
bool
|
|
operator!=(const OrganizationIdentifier& a, const OrganizationIdentifier& b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
|
|
/**
|
|
* less than operator
|
|
* \param a left side object
|
|
* \param b right side object
|
|
* \returns true if 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;
|
|
}
|
|
|
|
/**
|
|
* output operator
|
|
* \param os output stream
|
|
* \param oi organization identifier
|
|
* \returns output stream
|
|
*/
|
|
std::ostream&
|
|
operator<<(std::ostream& os, const OrganizationIdentifier& oi)
|
|
{
|
|
for (int i = 0; i < oi.m_type; i++)
|
|
{
|
|
os << "0x" << std::hex << static_cast<int>(oi.m_oi[i]) << " ";
|
|
}
|
|
os << std::endl;
|
|
return os;
|
|
}
|
|
|
|
/**
|
|
* input operator
|
|
* \param is input stream
|
|
* \param oi organization identifier
|
|
* \returns input stream
|
|
*/
|
|
std::istream&
|
|
operator>>(std::istream& is, const OrganizationIdentifier& oi)
|
|
{
|
|
return is;
|
|
}
|
|
|
|
/*********** VendorSpecificActionHeader *******/
|
|
NS_OBJECT_ENSURE_REGISTERED(VendorSpecificActionHeader);
|
|
|
|
VendorSpecificActionHeader::VendorSpecificActionHeader()
|
|
: m_oi(),
|
|
m_category(CATEGORY_OF_VSA)
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
}
|
|
|
|
VendorSpecificActionHeader::~VendorSpecificActionHeader()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
}
|
|
|
|
void
|
|
VendorSpecificActionHeader::SetOrganizationIdentifier(OrganizationIdentifier oi)
|
|
{
|
|
NS_LOG_FUNCTION(this << oi);
|
|
m_oi = oi;
|
|
}
|
|
|
|
OrganizationIdentifier
|
|
VendorSpecificActionHeader::GetOrganizationIdentifier() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_oi;
|
|
}
|
|
|
|
TypeId
|
|
VendorSpecificActionHeader::GetTypeId()
|
|
{
|
|
static TypeId tid = TypeId("ns3::VendorSpecificActionHeader")
|
|
.SetParent<Header>()
|
|
.SetGroupName("Wave")
|
|
.AddConstructor<VendorSpecificActionHeader>();
|
|
|
|
return tid;
|
|
}
|
|
|
|
uint8_t
|
|
VendorSpecificActionHeader::GetCategory() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_category;
|
|
}
|
|
|
|
TypeId
|
|
VendorSpecificActionHeader::GetInstanceTypeId() 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() 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()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
}
|
|
|
|
VendorSpecificContentManager::~VendorSpecificContentManager()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
}
|
|
|
|
void
|
|
VendorSpecificContentManager::RegisterVscCallback(OrganizationIdentifier oi, VscCallback cb)
|
|
{
|
|
NS_LOG_FUNCTION(this << oi << &cb);
|
|
if (IsVscCallbackRegistered(oi))
|
|
{
|
|
NS_LOG_WARN("there is already a VsaCallback registered for OrganizationIdentifier " << oi);
|
|
}
|
|
m_callbacks.insert(std::make_pair(oi, cb));
|
|
}
|
|
|
|
void
|
|
VendorSpecificContentManager::DeregisterVscCallback(OrganizationIdentifier& oi)
|
|
{
|
|
NS_LOG_FUNCTION(this << oi);
|
|
m_callbacks.erase(oi);
|
|
}
|
|
|
|
bool
|
|
VendorSpecificContentManager::IsVscCallbackRegistered(OrganizationIdentifier& oi)
|
|
{
|
|
NS_LOG_FUNCTION(this << oi);
|
|
if (m_callbacks.find(oi) == m_callbacks.end())
|
|
{
|
|
OrganizationIdentifiers.push_back(oi);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// VSC callback function
|
|
static VscCallback null_callback = MakeNullCallback<bool,
|
|
Ptr<WifiMac>,
|
|
const OrganizationIdentifier&,
|
|
Ptr<const Packet>,
|
|
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
|