Files
unison/src/wave/model/vendor-specific-action.cc
2022-10-14 14:13:12 +00:00

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