/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2008,2009 IITP RAS
*
* 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: Kirill Andreev <andreev@iitp.ru>
*/
#include "ie-dot11s-preq.h"
#include "ns3/address-utils.h"
#include "ns3/assert.h"
#include "ns3/packet.h"
namespace ns3 {
namespace dot11s {
/*************************
* DestinationAddressUnit
************************/
DestinationAddressUnit::DestinationAddressUnit () :
m_do (false), m_rf (false), m_usn (false), m_destinationAddress (Mac48Address ()), m_destSeqNumber (0)
{
}
void
DestinationAddressUnit::SetFlags (bool doFlag, bool rfFlag, bool usnFlag)
{
m_do = doFlag;
m_rf = rfFlag;
m_usn = usnFlag;
}
void
DestinationAddressUnit::SetDestSeqNumber (uint32_t dest_seq_number)
{
m_destSeqNumber = dest_seq_number;
if (m_destSeqNumber != 0)
{
m_usn = true;
}
}
void
DestinationAddressUnit::SetDestinationAddress (Mac48Address dest_address)
{
m_destinationAddress = dest_address;
}
bool
DestinationAddressUnit::IsDo ()
{
return m_do;
}
bool
DestinationAddressUnit::IsRf ()
{
return m_rf;
}
bool
DestinationAddressUnit::IsUsn ()
{
return m_usn;
}
uint32_t
DestinationAddressUnit::GetDestSeqNumber () const
{
return m_destSeqNumber;
}
Mac48Address
DestinationAddressUnit::GetDestinationAddress () const
{
return m_destinationAddress;
}
/********************************
* IePreq
*******************************/
IePreq::~IePreq ()
{
}
IePreq::IePreq () :
m_maxSize (32), m_flags (0), m_hopCount (0), m_ttl (0), m_preqId (0), m_originatorAddress (
Mac48Address::GetBroadcast ()), m_originatorSeqNumber (0), m_lifetime (0), m_metric (0),
m_destCount (0)
{
}
WifiElementId
IePreq::ElementId () const
{
return IE11S_PREQ;
}
void
IePreq::SetUnicastPreq ()
{
m_flags |= 1 << 1;
}
void
IePreq::SetNeedNotPrep ()
{
m_flags |= 1 << 2;
}
void
IePreq::SetHopcount (uint8_t hopcount)
{
m_hopCount = hopcount;
}
void
IePreq::SetTTL (uint8_t ttl)
{
m_ttl = ttl;
}
void
IePreq::SetPreqID (uint32_t preq_id)
{
m_preqId = preq_id;
}
void
IePreq::SetMetric (uint32_t metric)
{
m_metric = metric;
}
void
IePreq::SetOriginatorAddress (Mac48Address originator_address)
{
m_originatorAddress = originator_address;
}
void
IePreq::SetOriginatorSeqNumber (uint32_t originator_seq_number)
{
m_originatorSeqNumber = originator_seq_number;
}
void
IePreq::SetLifetime (uint32_t lifetime)
{
m_lifetime = lifetime;
}
void
IePreq::SetDestCount (uint8_t dest_count)
{
m_destCount = dest_count;
}
bool
IePreq::IsUnicastPreq () const
{
return (m_flags & (1 << 1));
}
bool
IePreq::IsNeedNotPrep () const
{
return (m_flags & (1 << 2));
}
uint8_t
IePreq::GetHopCount () const
{
return m_hopCount;
}
uint8_t
IePreq::GetTtl () const
{
return m_ttl;
}
uint32_t
IePreq::GetPreqID () const
{
return m_preqId;
}
uint32_t
IePreq::GetMetric () const
{
return m_metric;
}
Mac48Address
IePreq::GetOriginatorAddress () const
{
return m_originatorAddress;
}
uint32_t
IePreq::GetOriginatorSeqNumber () const
{
return m_originatorSeqNumber;
}
uint32_t
IePreq::GetLifetime () const
{
return m_lifetime;
}
uint8_t
IePreq::GetDestCount () const
{
return m_destCount;
}
void
IePreq::DecrementTtl ()
{
m_ttl--;
m_hopCount++;
}
void
IePreq::IncrementMetric (uint32_t metric)
{
m_metric += metric;
}
void
IePreq::SerializeInformation (Buffer::Iterator i) const
{
i.WriteU8 (m_flags);
i.WriteU8 (m_hopCount);
i.WriteU8 (m_ttl);
i.WriteHtolsbU32 (m_preqId);
WriteTo (i, m_originatorAddress);
i.WriteHtolsbU32 (m_originatorSeqNumber);
i.WriteHtolsbU32 (m_lifetime);
i.WriteHtolsbU32 (m_metric);
i.WriteU8 (m_destCount);
int written = 0;
for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator j = m_destinations.begin (); j
!= m_destinations.end (); j++)
{
uint8_t flags = 0;
if ((*j)->IsDo ())
{
flags |= 1 << 0;
}
if ((*j)->IsRf ())
{
flags |= 1 << 1;
}
if ((*j)->IsUsn ())
{
flags |= 1 << 2;
}
i.WriteU8 (flags);
WriteTo (i, (*j)->GetDestinationAddress ());
i.WriteHtolsbU32 ((*j)->GetDestSeqNumber ());
written++;
if (written > m_maxSize)
{
break;
}
}
}
uint8_t
IePreq::DeserializeInformation (Buffer::Iterator start, uint8_t length)
{
Buffer::Iterator i = start;
m_flags = i.ReadU8 ();
m_hopCount = i.ReadU8 ();
m_ttl = i.ReadU8 ();
m_preqId = i.ReadLsbtohU32 ();
ReadFrom (i, m_originatorAddress);
m_originatorSeqNumber = i.ReadLsbtohU32 ();
m_lifetime = i.ReadLsbtohU32 ();
m_metric = i.ReadLsbtohU32 ();
m_destCount = i.ReadU8 ();
for (int j = 0; j < m_destCount; j++)
{
Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit> ();
bool doFlag = false;
bool rfFlag = false;
bool usnFlag = false;
uint8_t flags = i.ReadU8 ();
if (flags & (1 << 0))
{
doFlag = true;
}
if (flags & (1 << 1))
{
rfFlag = true;
}
if (flags & (1 << 2))
{
usnFlag = true;
}
new_element->SetFlags (doFlag, rfFlag, usnFlag);
Mac48Address addr;
ReadFrom (i, addr);
new_element->SetDestinationAddress (addr);
new_element->SetDestSeqNumber (i.ReadLsbtohU32 ());
m_destinations.push_back (new_element);
NS_ASSERT (28 + j * 11 < length);
}
return i.GetDistanceFrom (start);
}
uint8_t
IePreq::GetInformationSize () const
{
uint8_t retval = 1 //Flags
+ 1 //Hopcount
+ 1 //TTL
+ 4 //PREQ ID
+ 6 //Source address (originator)
+ 4 //Originator seqno
+ 4 //Lifetime
+ 4 //metric
+ 1; //destination count
if (m_destCount > m_maxSize)
{
retval += (m_maxSize * 11);
}
else
{
retval += (m_destCount * 11);
}
return retval;
}
void
IePreq::Print (std::ostream &os) const
{
os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
os << " originator address = " << m_originatorAddress << "std::endl";
os << " TTL = " << (uint16_t) m_ttl << "std::endl";
os << " hop count = " << (uint16_t) m_hopCount << "std::endl";
os << " metric = " << m_metric << "std::endl";
os << " seqno = " << m_originatorSeqNumber << "std::endl";
os << " lifetime = " << m_lifetime << "std::endl";
os << " preq ID = " << m_preqId << "std::endl";
os << " Destinations are:std::endl";
for (int j = 0; j < m_destCount; j++)
{
os << " " << m_destinations[j]->GetDestinationAddress () << "std::endl";
}
os << "</information_element>" << std::endl;
}
std::vector<Ptr<DestinationAddressUnit> >
IePreq::GetDestinationList ()
{
return m_destinations;
}
void
IePreq::AddDestinationAddressElement (bool doFlag, bool rfFlag, Mac48Address dest_address,
uint32_t dest_seq_number)
{
for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = m_destinations.begin (); i
!= m_destinations.end (); i++)
{
if ((*i)->GetDestinationAddress () == dest_address)
{
return;
}
}
//TODO: check overflow
Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit> ();
new_element->SetFlags (doFlag, rfFlag, (dest_seq_number == 0));
new_element->SetDestinationAddress (dest_address);
new_element->SetDestSeqNumber (dest_seq_number);
m_destinations.push_back (new_element);
m_destCount++;
}
void
IePreq::DelDestinationAddressElement (Mac48Address dest_address)
{
for (std::vector<Ptr<DestinationAddressUnit> >::iterator i = m_destinations.begin (); i
!= m_destinations.end (); i++)
{
if ((*i)->GetDestinationAddress () == dest_address)
{
m_destinations.erase (i);
m_destCount--;
break;
}
}
}
void
IePreq::ClearDestinationAddressElements ()
{
for (std::vector<Ptr<DestinationAddressUnit> >::iterator j = m_destinations.begin (); j
!= m_destinations.end (); j++)
{
(*j) = 0;
}
m_destinations.clear ();
m_destCount = 0;
}
bool
operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b)
{
return (a.m_do == b.m_do && a.m_rf == b.m_rf && a.m_usn == b.m_usn && a.m_destinationAddress
== b.m_destinationAddress && a.m_destSeqNumber == b.m_destSeqNumber);
}
bool
operator== (const IePreq & a, const IePreq & b)
{
bool ok = (a.m_flags == b.m_flags && a.m_hopCount == b.m_hopCount && a.m_ttl == b.m_ttl && a.m_preqId
== b.m_preqId && a.m_originatorAddress == b.m_originatorAddress && a.m_originatorSeqNumber
== b.m_originatorSeqNumber && a.m_lifetime == b.m_lifetime && a.m_metric == b.m_metric && a.m_destCount
== b.m_destCount);
if (!ok)
{
return false;
}
if (a.m_destinations.size () != b.m_destinations.size ())
{
return false;
}
for (size_t i = 0; i < a.m_destinations.size (); ++i)
{
if (!(*(PeekPointer (a.m_destinations[i])) == *(PeekPointer (b.m_destinations[i]))))
{
return false;
}
}
return true;
}
bool
IePreq::MayAddAddress (Mac48Address originator)
{
if (m_originatorAddress != originator)
{
return false;
}
if (m_destinations[0]->GetDestinationAddress () == Mac48Address::GetBroadcast ())
{
return false;
}
if ((GetInformationSize () + 11) > 255)
{
return false;
}
return true;
}
bool
IePreq::IsFull () const
{
return ((GetInformationSize () + 11) > 255);
}
std::ostream &
operator << (std::ostream &os, const IePreq &a)
{
a.Print (os);
return os;
}
} // namespace dot11s
} //namespace ns3