1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2007, 2008 University of Washington
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "ns3/queue.h"
21 #include "ns3/simulator.h"
22 #include "ns3/mac48-address.h"
23 #include "ns3/llc-snap-header.h"
24 #include "ns3/error-model.h"
25 #include "ns3/trace-source-accessor.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/pointer.h"
28 #include "point-to-point-net-device.h"
29 #include "point-to-point-channel.h"
30 #include "ppp-header.h"
32 NS_LOG_COMPONENT_DEFINE ("PointToPointNetDevice");
36 NS_OBJECT_ENSURE_REGISTERED (PointToPointNetDevice);
39 PointToPointNetDevice::GetTypeId (void)
41 static TypeId tid = TypeId ("ns3::PointToPointNetDevice")
42 .SetParent<NetDevice> ()
43 .AddConstructor<PointToPointNetDevice> ()
44 .AddAttribute ("Address",
45 "The MAC address of this device.",
46 Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
47 MakeMac48AddressAccessor (&PointToPointNetDevice::m_address),
48 MakeMac48AddressChecker ())
49 .AddAttribute ("FrameSize",
50 "The maximum size of a packet sent over this device.",
51 UintegerValue (DEFAULT_FRAME_SIZE),
52 MakeUintegerAccessor (&PointToPointNetDevice::SetFrameSize,
53 &PointToPointNetDevice::GetFrameSize),
54 MakeUintegerChecker<uint16_t> ())
55 .AddAttribute ("DataRate",
56 "The default data rate for point to point links",
57 DataRateValue (DataRate ("32768b/s")),
58 MakeDataRateAccessor (&PointToPointNetDevice::m_bps),
59 MakeDataRateChecker ())
60 .AddAttribute ("ReceiveErrorModel",
61 "The receiver error model used to simulate packet loss",
63 MakePointerAccessor (&PointToPointNetDevice::m_receiveErrorModel),
64 MakePointerChecker<ErrorModel> ())
65 .AddAttribute ("TxQueue",
66 "A queue to use as the transmit queue in the device.",
68 MakePointerAccessor (&PointToPointNetDevice::m_queue),
69 MakePointerChecker<Queue> ())
70 .AddAttribute ("InterframeGap",
71 "The time to wait between packet (frame) transmissions",
72 TimeValue (Seconds (0.0)),
73 MakeTimeAccessor (&PointToPointNetDevice::m_tInterframeGap),
75 .AddTraceSource ("Rx",
76 "Trace source to fire on reception of a MAC packet.",
77 MakeTraceSourceAccessor (&PointToPointNetDevice::m_rxTrace))
78 .AddTraceSource ("Drop",
79 "Trace source to fire on when a MAC packet is dropped.",
81 MakeTraceSourceAccessor (&PointToPointNetDevice::m_dropTrace))
88 PointToPointNetDevice::PointToPointNetDevice ()
90 m_txMachineState (READY),
95 NS_LOG_FUNCTION (this);
98 // A quick sanity check to ensure consistent constants.
101 NS_ASSERT_MSG (PPP_OVERHEAD == ppp.GetSerializedSize (),
102 "PointToPointNetDevice::PointToPointNetDevice(): PPP_OVERHEAD inconsistent");
104 m_frameSize = DEFAULT_FRAME_SIZE;
105 m_mtu = MtuFromFrameSize (m_frameSize);
108 PointToPointNetDevice::~PointToPointNetDevice ()
113 PointToPointNetDevice::AddHeader(Ptr<Packet> p, uint16_t protocolNumber)
115 NS_LOG_FUNCTION_NOARGS ();
116 NS_ASSERT_MSG (protocolNumber == 0x800,
117 "PointToPointNetDevice::AddHeader(): protocolNumber must be 0x800");
123 PointToPointNetDevice::ProcessHeader(Ptr<Packet> p, uint16_t& param)
125 NS_LOG_FUNCTION_NOARGS ();
127 p->RemoveHeader (ppp);
133 PointToPointNetDevice::DoDispose()
135 NS_LOG_FUNCTION_NOARGS ();
138 m_receiveErrorModel = 0;
139 NetDevice::DoDispose ();
143 PointToPointNetDevice::SetDataRate(DataRate bps)
145 NS_LOG_FUNCTION_NOARGS ();
150 PointToPointNetDevice::SetInterframeGap(Time t)
152 NS_LOG_FUNCTION_NOARGS ();
153 m_tInterframeGap = t;
157 PointToPointNetDevice::TransmitStart (Ptr<Packet> p)
159 NS_LOG_FUNCTION (this << p);
160 NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
162 // This function is called to start the process of transmitting a packet.
163 // We need to tell the channel that we've started wiggling the wire and
164 // schedule an event that will be executed when the transmission is complete.
166 NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
167 m_txMachineState = BUSY;
168 Time txTime = Seconds (m_bps.CalculateTxTime(p->GetSize()));
169 Time txCompleteTime = txTime + m_tInterframeGap;
171 NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " <<
172 txCompleteTime.GetSeconds () << "sec");
174 Simulator::Schedule (txCompleteTime,
175 &PointToPointNetDevice::TransmitComplete, this);
177 return m_channel->TransmitStart(p, this, txTime);
181 PointToPointNetDevice::TransmitComplete (void)
183 NS_LOG_FUNCTION_NOARGS ();
185 // This function is called to when we're all done transmitting a packet.
186 // We try and pull another packet off of the transmit queue. If the queue
187 // is empty, we are done, otherwise we need to start transmitting the
190 NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
191 m_txMachineState = READY;
192 Ptr<Packet> p = m_queue->Dequeue ();
196 // No packet was on the queue, so we just exit.
201 // Got another packet off of the queue, so start the transmit process agin.
207 PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
209 NS_LOG_FUNCTION (this << &ch);
213 m_channel->Attach(this);
216 // This device is up whenever it is attached to a channel. A better plan
217 // would be to have the link come up when both devices are attached, but this
218 // is not done for now.
225 PointToPointNetDevice::SetQueue (Ptr<Queue> q)
227 NS_LOG_FUNCTION (this << q);
232 PointToPointNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
234 NS_LOG_FUNCTION (this << em);
235 m_receiveErrorModel = em;
239 PointToPointNetDevice::Receive (Ptr<Packet> packet)
241 NS_LOG_FUNCTION (this << packet);
242 uint16_t protocol = 0;
244 if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
247 // If we have an error model and it indicates that it is time to lose a
248 // corrupted packet, don't forward this packet up, let it go.
250 m_dropTrace (packet);
255 // Hit the receive trace hook, strip off the point-to-point protocol header
256 // and forward this packet up the protocol stack.
259 ProcessHeader(packet, protocol);
260 m_rxCallback (this, packet, protocol, GetRemote ());
261 if (!m_promiscCallback.IsNull ())
263 m_promiscCallback (this, packet, protocol, GetRemote (), GetAddress (), NetDevice::PACKET_HOST);
269 PointToPointNetDevice::GetQueue(void) const
271 NS_LOG_FUNCTION_NOARGS ();
276 PointToPointNetDevice::NotifyLinkUp (void)
279 if (!m_linkChangeCallback.IsNull ())
281 m_linkChangeCallback ();
286 PointToPointNetDevice::SetName(const std::string name)
292 PointToPointNetDevice::GetName(void) const
298 PointToPointNetDevice::SetIfIndex(const uint32_t index)
304 PointToPointNetDevice::GetIfIndex(void) const
310 PointToPointNetDevice::GetChannel (void) const
316 // This is a point-to-point device, so we really don't need any kind of address
317 // information. However, the base class NetDevice wants us to define the
318 // methods to get and set the address. Rather than be rude and assert, we let
319 // clients get and set the address, but simply ignore them.
321 PointToPointNetDevice::SetAddress (Mac48Address addr)
327 PointToPointNetDevice::GetAddress (void) const
333 PointToPointNetDevice::IsLinkUp (void) const
339 PointToPointNetDevice::SetLinkChangeCallback (Callback<void> callback)
341 m_linkChangeCallback = callback;
345 // This is a point-to-point device, so every transmission is a broadcast to
346 // all of the devices on the network.
349 PointToPointNetDevice::IsBroadcast (void) const
355 // We don't really need any addressing information since this is a
356 // point-to-point device. The base class NetDevice wants us to return a
357 // broadcast address, so we make up something reasonable.
360 PointToPointNetDevice::GetBroadcast (void) const
362 return Mac48Address ("ff:ff:ff:ff:ff:ff");
366 // We don't deal with multicast here. It doesn't make sense to include some
367 // of the one destinations on the network but exclude some of the others.
370 PointToPointNetDevice::IsMulticast (void) const
376 PointToPointNetDevice::GetMulticast (Ipv4Address multicastGroup) const
378 return Mac48Address ("01:00:5e:00:00:00");
382 PointToPointNetDevice::GetMulticast (Ipv6Address addr) const
384 NS_LOG_FUNCTION(this << addr);
385 return Mac48Address ("33:33:00:00:00:00");
389 PointToPointNetDevice::IsPointToPoint (void) const
395 PointToPointNetDevice::Send(
398 uint16_t protocolNumber)
400 NS_LOG_FUNCTION_NOARGS ();
401 NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest);
402 NS_LOG_LOGIC ("UID is " << packet->GetUid ());
405 // If IsLinkUp() is false it means there is no channel to send any packet
406 // over so we just return an error.
408 if (IsLinkUp () == false)
414 // Stick a point to point protocol header on the packet in preparation for
415 // shoving it out the door.
417 AddHeader(packet, protocolNumber);
420 // If there's a transmission in progress, we enque the packet for later
421 // transmission; otherwise we send it now.
423 if (m_txMachineState == READY)
426 // Even if the transmitter is immediately available, we still enqueue and
427 // dequeue the packet to hit the tracing hooks.
429 m_queue->Enqueue (packet);
430 packet = m_queue->Dequeue ();
431 return TransmitStart (packet);
435 return m_queue->Enqueue(packet);
440 PointToPointNetDevice::SendFrom (Ptr<Packet> packet,
441 const Address &source,
443 uint16_t protocolNumber)
449 PointToPointNetDevice::GetNode (void) const
455 PointToPointNetDevice::SetNode (Ptr<Node> node)
461 PointToPointNetDevice::NeedsArp (void) const
467 PointToPointNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
473 PointToPointNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
475 NS_FATAL_ERROR ("not implemented");
476 m_promiscCallback = cb;
480 PointToPointNetDevice::SupportsSendFrom (void) const
486 PointToPointNetDevice::GetRemote (void) const
488 NS_ASSERT (m_channel->GetNDevices () == 2);
489 for (uint32_t i = 0; i < m_channel->GetNDevices (); ++i)
491 Ptr<NetDevice> tmp = m_channel->GetDevice (i);
494 return tmp->GetAddress ();
503 PointToPointNetDevice::MtuFromFrameSize (uint32_t frameSize)
505 NS_LOG_FUNCTION (frameSize);
506 NS_ASSERT_MSG (frameSize <= std::numeric_limits<uint16_t>::max (),
507 "PointToPointNetDevice::MtuFromFrameSize(): Frame size should be derived from 16-bit quantity: " <<
510 NS_ASSERT_MSG ((uint32_t)frameSize >= ppp.GetSerializedSize (),
511 "PointToPointNetDevice::MtuFromFrameSize(): Given frame size too small to support PPP");
512 return frameSize - ppp.GetSerializedSize ();
516 PointToPointNetDevice::FrameSizeFromMtu (uint32_t mtu)
518 NS_LOG_FUNCTION (mtu);
521 return mtu + ppp.GetSerializedSize ();
525 PointToPointNetDevice::SetFrameSize (uint16_t frameSize)
527 NS_LOG_FUNCTION (frameSize);
529 m_frameSize = frameSize;
530 m_mtu = MtuFromFrameSize (frameSize);
532 NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
533 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
537 PointToPointNetDevice::GetFrameSize (void) const
543 PointToPointNetDevice::SetMtu (uint16_t mtu)
545 NS_LOG_FUNCTION (mtu);
547 uint32_t newFrameSize = FrameSizeFromMtu (mtu);
549 if (newFrameSize > std::numeric_limits<uint16_t>::max ())
551 NS_LOG_WARN ("PointToPointNetDevice::SetMtu(): Frame size overflow, MTU not set.");
555 m_frameSize = newFrameSize;
558 NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
559 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
565 PointToPointNetDevice::GetMtu (void) const
567 NS_LOG_FUNCTION_NOARGS ();