562 lines
12 KiB
C++
562 lines
12 KiB
C++
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
/*
|
|
* Copyright (c) 2008 INRIA
|
|
*
|
|
* 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 <mathieu.lacage@sophia.inria.fr>
|
|
*/
|
|
#include "simple-net-device.h"
|
|
#include "simple-channel.h"
|
|
#include "ns3/node.h"
|
|
#include "ns3/packet.h"
|
|
#include "ns3/log.h"
|
|
#include "ns3/pointer.h"
|
|
#include "ns3/error-model.h"
|
|
#include "ns3/trace-source-accessor.h"
|
|
#include "ns3/boolean.h"
|
|
#include "ns3/string.h"
|
|
#include "ns3/tag.h"
|
|
#include "ns3/simulator.h"
|
|
#include "ns3/drop-tail-queue.h"
|
|
|
|
namespace ns3 {
|
|
|
|
NS_LOG_COMPONENT_DEFINE ("SimpleNetDevice");
|
|
|
|
/**
|
|
* \brief SimpleNetDevice tag to store source, destination and protocol of each packet.
|
|
*/
|
|
class SimpleTag : public Tag {
|
|
public:
|
|
/**
|
|
* \brief Get the type ID.
|
|
* \return the object TypeId
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* Set the source address
|
|
* \param src source address
|
|
*/
|
|
void SetSrc (Mac48Address src);
|
|
/**
|
|
* Get the source address
|
|
* \return the source address
|
|
*/
|
|
Mac48Address GetSrc (void) const;
|
|
|
|
/**
|
|
* Set the destination address
|
|
* \param dst destination address
|
|
*/
|
|
void SetDst (Mac48Address dst);
|
|
/**
|
|
* Get the destination address
|
|
* \return the destination address
|
|
*/
|
|
Mac48Address GetDst (void) const;
|
|
|
|
/**
|
|
* Set the protocol number
|
|
* \param proto protocol number
|
|
*/
|
|
void SetProto (uint16_t proto);
|
|
/**
|
|
* Get the protocol number
|
|
* \return the protocol number
|
|
*/
|
|
uint16_t GetProto (void) const;
|
|
|
|
void Print (std::ostream &os) const;
|
|
|
|
private:
|
|
Mac48Address m_src; //!< source address
|
|
Mac48Address m_dst; //!< destination address
|
|
uint16_t m_protocolNumber; //!< protocol number
|
|
};
|
|
|
|
|
|
NS_OBJECT_ENSURE_REGISTERED (SimpleTag);
|
|
|
|
TypeId
|
|
SimpleTag::GetTypeId (void)
|
|
{
|
|
static TypeId tid = TypeId ("SimpleTag")
|
|
.SetParent<Tag> ()
|
|
.AddConstructor<SimpleTag> ()
|
|
;
|
|
return tid;
|
|
}
|
|
TypeId
|
|
SimpleTag::GetInstanceTypeId (void) const
|
|
{
|
|
return GetTypeId ();
|
|
}
|
|
|
|
uint32_t
|
|
SimpleTag::GetSerializedSize (void) const
|
|
{
|
|
return 8+8+2;
|
|
}
|
|
void
|
|
SimpleTag::Serialize (TagBuffer i) const
|
|
{
|
|
uint8_t mac[6];
|
|
m_src.CopyTo (mac);
|
|
i.Write (mac, 6);
|
|
m_dst.CopyTo (mac);
|
|
i.Write (mac, 6);
|
|
i.WriteU16 (m_protocolNumber);
|
|
}
|
|
void
|
|
SimpleTag::Deserialize (TagBuffer i)
|
|
{
|
|
uint8_t mac[6];
|
|
i.Read (mac, 6);
|
|
m_src.CopyFrom (mac);
|
|
i.Read (mac, 6);
|
|
m_dst.CopyFrom (mac);
|
|
m_protocolNumber = i.ReadU16 ();
|
|
}
|
|
|
|
void
|
|
SimpleTag::SetSrc (Mac48Address src)
|
|
{
|
|
m_src = src;
|
|
}
|
|
|
|
Mac48Address
|
|
SimpleTag::GetSrc (void) const
|
|
{
|
|
return m_src;
|
|
}
|
|
|
|
void
|
|
SimpleTag::SetDst (Mac48Address dst)
|
|
{
|
|
m_dst = dst;
|
|
}
|
|
|
|
Mac48Address
|
|
SimpleTag::GetDst (void) const
|
|
{
|
|
return m_dst;
|
|
}
|
|
|
|
void
|
|
SimpleTag::SetProto (uint16_t proto)
|
|
{
|
|
m_protocolNumber = proto;
|
|
}
|
|
|
|
uint16_t
|
|
SimpleTag::GetProto (void) const
|
|
{
|
|
return m_protocolNumber;
|
|
}
|
|
|
|
void
|
|
SimpleTag::Print (std::ostream &os) const
|
|
{
|
|
os << "src=" << m_src << " dst=" << m_dst << " proto=" << m_protocolNumber;
|
|
}
|
|
|
|
|
|
|
|
NS_OBJECT_ENSURE_REGISTERED (SimpleNetDevice);
|
|
|
|
TypeId
|
|
SimpleNetDevice::GetTypeId (void)
|
|
{
|
|
static TypeId tid = TypeId ("ns3::SimpleNetDevice")
|
|
.SetParent<NetDevice> ()
|
|
.AddConstructor<SimpleNetDevice> ()
|
|
.AddAttribute ("ReceiveErrorModel",
|
|
"The receiver error model used to simulate packet loss",
|
|
PointerValue (),
|
|
MakePointerAccessor (&SimpleNetDevice::m_receiveErrorModel),
|
|
MakePointerChecker<ErrorModel> ())
|
|
.AddAttribute ("PointToPointMode",
|
|
"The device is configured in Point to Point mode",
|
|
BooleanValue (false),
|
|
MakeBooleanAccessor (&SimpleNetDevice::m_pointToPointMode),
|
|
MakeBooleanChecker ())
|
|
.AddAttribute ("TxQueue",
|
|
"A queue to use as the transmit queue in the device.",
|
|
StringValue ("ns3::DropTailQueue"),
|
|
MakePointerAccessor (&SimpleNetDevice::m_queue),
|
|
MakePointerChecker<Queue> ())
|
|
.AddAttribute ("DataRate",
|
|
"The default data rate for point to point links. Zero means infinite",
|
|
DataRateValue (DataRate ("0b/s")),
|
|
MakeDataRateAccessor (&SimpleNetDevice::m_bps),
|
|
MakeDataRateChecker ())
|
|
.AddTraceSource ("PhyRxDrop",
|
|
"Trace source indicating a packet has been dropped "
|
|
"by the device during reception",
|
|
MakeTraceSourceAccessor (&SimpleNetDevice::m_phyRxDropTrace),
|
|
"ns3::Packet::TracedCallback")
|
|
;
|
|
return tid;
|
|
}
|
|
|
|
SimpleNetDevice::SimpleNetDevice ()
|
|
: m_channel (0),
|
|
m_node (0),
|
|
m_mtu (0xffff),
|
|
m_ifIndex (0),
|
|
m_linkUp (false)
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
}
|
|
|
|
void
|
|
SimpleNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol,
|
|
Mac48Address to, Mac48Address from)
|
|
{
|
|
NS_LOG_FUNCTION (this << packet << protocol << to << from);
|
|
NetDevice::PacketType packetType;
|
|
|
|
if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
|
|
{
|
|
m_phyRxDropTrace (packet);
|
|
return;
|
|
}
|
|
|
|
if (to == m_address)
|
|
{
|
|
packetType = NetDevice::PACKET_HOST;
|
|
}
|
|
else if (to.IsBroadcast ())
|
|
{
|
|
packetType = NetDevice::PACKET_BROADCAST;
|
|
}
|
|
else if (to.IsGroup ())
|
|
{
|
|
packetType = NetDevice::PACKET_MULTICAST;
|
|
}
|
|
else
|
|
{
|
|
packetType = NetDevice::PACKET_OTHERHOST;
|
|
}
|
|
|
|
if (packetType != NetDevice::PACKET_OTHERHOST)
|
|
{
|
|
m_rxCallback (this, packet, protocol, from);
|
|
}
|
|
|
|
if (!m_promiscCallback.IsNull ())
|
|
{
|
|
m_promiscCallback (this, packet, protocol, from, to, packetType);
|
|
}
|
|
}
|
|
|
|
void
|
|
SimpleNetDevice::SetChannel (Ptr<SimpleChannel> channel)
|
|
{
|
|
NS_LOG_FUNCTION (this << channel);
|
|
m_channel = channel;
|
|
m_channel->Add (this);
|
|
m_linkUp = true;
|
|
m_linkChangeCallbacks ();
|
|
}
|
|
|
|
Ptr<Queue>
|
|
SimpleNetDevice::GetQueue () const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return m_queue;
|
|
}
|
|
|
|
void
|
|
SimpleNetDevice::SetQueue (Ptr<Queue> q)
|
|
{
|
|
NS_LOG_FUNCTION (this << q);
|
|
m_queue = q;
|
|
}
|
|
|
|
void
|
|
SimpleNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
|
|
{
|
|
NS_LOG_FUNCTION (this << em);
|
|
m_receiveErrorModel = em;
|
|
}
|
|
|
|
void
|
|
SimpleNetDevice::SetIfIndex (const uint32_t index)
|
|
{
|
|
NS_LOG_FUNCTION (this << index);
|
|
m_ifIndex = index;
|
|
}
|
|
uint32_t
|
|
SimpleNetDevice::GetIfIndex (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return m_ifIndex;
|
|
}
|
|
Ptr<Channel>
|
|
SimpleNetDevice::GetChannel (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return m_channel;
|
|
}
|
|
void
|
|
SimpleNetDevice::SetAddress (Address address)
|
|
{
|
|
NS_LOG_FUNCTION (this << address);
|
|
m_address = Mac48Address::ConvertFrom (address);
|
|
}
|
|
Address
|
|
SimpleNetDevice::GetAddress (void) const
|
|
{
|
|
//
|
|
// Implicit conversion from Mac48Address to Address
|
|
//
|
|
NS_LOG_FUNCTION (this);
|
|
return m_address;
|
|
}
|
|
bool
|
|
SimpleNetDevice::SetMtu (const uint16_t mtu)
|
|
{
|
|
NS_LOG_FUNCTION (this << mtu);
|
|
m_mtu = mtu;
|
|
return true;
|
|
}
|
|
uint16_t
|
|
SimpleNetDevice::GetMtu (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return m_mtu;
|
|
}
|
|
bool
|
|
SimpleNetDevice::IsLinkUp (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return m_linkUp;
|
|
}
|
|
void
|
|
SimpleNetDevice::AddLinkChangeCallback (Callback<void> callback)
|
|
{
|
|
NS_LOG_FUNCTION (this << &callback);
|
|
m_linkChangeCallbacks.ConnectWithoutContext (callback);
|
|
}
|
|
bool
|
|
SimpleNetDevice::IsBroadcast (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
if (m_pointToPointMode)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
Address
|
|
SimpleNetDevice::GetBroadcast (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return Mac48Address ("ff:ff:ff:ff:ff:ff");
|
|
}
|
|
bool
|
|
SimpleNetDevice::IsMulticast (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
if (m_pointToPointMode)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
Address
|
|
SimpleNetDevice::GetMulticast (Ipv4Address multicastGroup) const
|
|
{
|
|
NS_LOG_FUNCTION (this << multicastGroup);
|
|
return Mac48Address::GetMulticast (multicastGroup);
|
|
}
|
|
|
|
Address SimpleNetDevice::GetMulticast (Ipv6Address addr) const
|
|
{
|
|
NS_LOG_FUNCTION (this << addr);
|
|
return Mac48Address::GetMulticast (addr);
|
|
}
|
|
|
|
bool
|
|
SimpleNetDevice::IsPointToPoint (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
if (m_pointToPointMode)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SimpleNetDevice::IsBridge (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SimpleNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
|
|
{
|
|
NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
|
|
|
|
return SendFrom (packet, m_address, dest, protocolNumber);
|
|
}
|
|
|
|
bool
|
|
SimpleNetDevice::SendFrom (Ptr<Packet> p, const Address& source, const Address& dest, uint16_t protocolNumber)
|
|
{
|
|
NS_LOG_FUNCTION (this << p << source << dest << protocolNumber);
|
|
if (p->GetSize () > GetMtu ())
|
|
{
|
|
return false;
|
|
}
|
|
Ptr<Packet> packet = p->Copy ();
|
|
|
|
Mac48Address to = Mac48Address::ConvertFrom (dest);
|
|
Mac48Address from = Mac48Address::ConvertFrom (source);
|
|
|
|
SimpleTag tag;
|
|
tag.SetSrc (from);
|
|
tag.SetDst (to);
|
|
tag.SetProto (protocolNumber);
|
|
|
|
p->AddPacketTag (tag);
|
|
|
|
if (m_queue->Enqueue (p))
|
|
{
|
|
if (m_queue->GetNPackets () == 1)
|
|
{
|
|
p = m_queue->Dequeue ();
|
|
p->RemovePacketTag (tag);
|
|
Time txTime = Time (0);
|
|
if (m_bps > DataRate (0))
|
|
{
|
|
txTime = m_bps.CalculateBytesTxTime (packet->GetSize ());
|
|
}
|
|
m_channel->Send (p, protocolNumber, to, from, this);
|
|
TransmitCompleteEvent = Simulator::Schedule (txTime, &SimpleNetDevice::TransmitComplete, this);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
m_channel->Send (packet, protocolNumber, to, from, this);
|
|
return true;
|
|
}
|
|
|
|
|
|
void
|
|
SimpleNetDevice::TransmitComplete ()
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
|
|
if (m_queue->GetNPackets () == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Ptr<Packet> packet = m_queue->Dequeue ();
|
|
|
|
SimpleTag tag;
|
|
packet->RemovePacketTag (tag);
|
|
|
|
Mac48Address src = tag.GetSrc ();
|
|
Mac48Address dst = tag.GetDst ();
|
|
uint16_t proto = tag.GetProto ();
|
|
|
|
m_channel->Send (packet, proto, dst, src, this);
|
|
|
|
if (m_queue->GetNPackets ())
|
|
{
|
|
Time txTime = Time (0);
|
|
if (m_bps > DataRate (0))
|
|
{
|
|
txTime = m_bps.CalculateBytesTxTime (packet->GetSize ());
|
|
}
|
|
TransmitCompleteEvent = Simulator::Schedule (txTime, &SimpleNetDevice::TransmitComplete, this);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
Ptr<Node>
|
|
SimpleNetDevice::GetNode (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return m_node;
|
|
}
|
|
void
|
|
SimpleNetDevice::SetNode (Ptr<Node> node)
|
|
{
|
|
NS_LOG_FUNCTION (this << node);
|
|
m_node = node;
|
|
}
|
|
bool
|
|
SimpleNetDevice::NeedsArp (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
if (m_pointToPointMode)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
void
|
|
SimpleNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
|
|
{
|
|
NS_LOG_FUNCTION (this << &cb);
|
|
m_rxCallback = cb;
|
|
}
|
|
|
|
void
|
|
SimpleNetDevice::DoDispose (void)
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
m_channel = 0;
|
|
m_node = 0;
|
|
m_receiveErrorModel = 0;
|
|
m_queue->DequeueAll ();
|
|
if (TransmitCompleteEvent.IsRunning ())
|
|
{
|
|
TransmitCompleteEvent.Cancel ();
|
|
}
|
|
NetDevice::DoDispose ();
|
|
}
|
|
|
|
|
|
void
|
|
SimpleNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
|
|
{
|
|
NS_LOG_FUNCTION (this << &cb);
|
|
m_promiscCallback = cb;
|
|
}
|
|
|
|
bool
|
|
SimpleNetDevice::SupportsSendFrom (void) const
|
|
{
|
|
NS_LOG_FUNCTION (this);
|
|
return true;
|
|
}
|
|
|
|
} // namespace ns3
|