A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
point-to-point-net-device.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007, 2008 University of Washington
4  *
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;
8  *
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.
13  *
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
17  */
18 
19 #include "ns3/log.h"
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 "ns3/mpi-interface.h"
29 #include "point-to-point-net-device.h"
30 #include "point-to-point-channel.h"
31 #include "ppp-header.h"
32 
33 NS_LOG_COMPONENT_DEFINE ("PointToPointNetDevice");
34 
35 namespace ns3 {
36 
37 NS_OBJECT_ENSURE_REGISTERED (PointToPointNetDevice);
38 
39 TypeId
40 PointToPointNetDevice::GetTypeId (void)
41 {
42  static TypeId tid = TypeId ("ns3::PointToPointNetDevice")
43  .SetParent<NetDevice> ()
44  .AddConstructor<PointToPointNetDevice> ()
45  .AddAttribute ("Mtu", "The MAC-level Maximum Transmission Unit",
46  UintegerValue (DEFAULT_MTU),
47  MakeUintegerAccessor (&PointToPointNetDevice::SetMtu,
49  MakeUintegerChecker<uint16_t> ())
50  .AddAttribute ("Address",
51  "The MAC address of this device.",
52  Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
53  MakeMac48AddressAccessor (&PointToPointNetDevice::m_address),
54  MakeMac48AddressChecker ())
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",
62  PointerValue (),
63  MakePointerAccessor (&PointToPointNetDevice::m_receiveErrorModel),
64  MakePointerChecker<ErrorModel> ())
65  .AddAttribute ("InterframeGap",
66  "The time to wait between packet (frame) transmissions",
67  TimeValue (Seconds (0.0)),
68  MakeTimeAccessor (&PointToPointNetDevice::m_tInterframeGap),
69  MakeTimeChecker ())
70 
71  //
72  // Transmit queueing discipline for the device which includes its own set
73  // of trace hooks.
74  //
75  .AddAttribute ("TxQueue",
76  "A queue to use as the transmit queue in the device.",
77  PointerValue (),
78  MakePointerAccessor (&PointToPointNetDevice::m_queue),
79  MakePointerChecker<Queue> ())
80 
81  //
82  // Trace sources at the "top" of the net device, where packets transition
83  // to/from higher layers.
84  //
85  .AddTraceSource ("MacTx",
86  "Trace source indicating a packet has arrived for transmission by this device",
88  .AddTraceSource ("MacTxDrop",
89  "Trace source indicating a packet has been dropped by the device before transmission",
91  .AddTraceSource ("MacPromiscRx",
92  "A packet has been received by this device, has been passed up from the physical layer "
93  "and is being forwarded up the local protocol stack. This is a promiscuous trace,",
95  .AddTraceSource ("MacRx",
96  "A packet has been received by this device, has been passed up from the physical layer "
97  "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,",
99 #if 0
100  // Not currently implemented for this device
101  .AddTraceSource ("MacRxDrop",
102  "Trace source indicating a packet was dropped before being forwarded up the stack",
104 #endif
105  //
106  // Trace souces at the "bottom" of the net device, where packets transition
107  // to/from the channel.
108  //
109  .AddTraceSource ("PhyTxBegin",
110  "Trace source indicating a packet has begun transmitting over the channel",
112  .AddTraceSource ("PhyTxEnd",
113  "Trace source indicating a packet has been completely transmitted over the channel",
115  .AddTraceSource ("PhyTxDrop",
116  "Trace source indicating a packet has been dropped by the device during transmission",
118 #if 0
119  // Not currently implemented for this device
120  .AddTraceSource ("PhyRxBegin",
121  "Trace source indicating a packet has begun being received by the device",
123 #endif
124  .AddTraceSource ("PhyRxEnd",
125  "Trace source indicating a packet has been completely received by the device",
127  .AddTraceSource ("PhyRxDrop",
128  "Trace source indicating a packet has been dropped by the device during reception",
130 
131  //
132  // Trace sources designed to simulate a packet sniffer facility (tcpdump).
133  // Note that there is really no difference between promiscuous and
134  // non-promiscuous traces in a point-to-point link.
135  //
136  .AddTraceSource ("Sniffer",
137  "Trace source simulating a non-promiscuous packet sniffer attached to the device",
139  .AddTraceSource ("PromiscSniffer",
140  "Trace source simulating a promiscuous packet sniffer attached to the device",
142  ;
143  return tid;
144 }
145 
146 
148  :
149  m_txMachineState (READY),
150  m_channel (0),
151  m_linkUp (false),
152  m_currentPkt (0)
153 {
154  NS_LOG_FUNCTION (this);
155 }
156 
158 {
160 }
161 
162 void
163 PointToPointNetDevice::AddHeader (Ptr<Packet> p, uint16_t protocolNumber)
164 {
166  PppHeader ppp;
167  ppp.SetProtocol (EtherToPpp (protocolNumber));
168  p->AddHeader (ppp);
169 }
170 
171 bool
173 {
175  PppHeader ppp;
176  p->RemoveHeader (ppp);
177  param = PppToEther (ppp.GetProtocol ());
178  return true;
179 }
180 
181 void
183 {
185  m_node = 0;
186  m_channel = 0;
188  m_currentPkt = 0;
190 }
191 
192 void
194 {
196  m_bps = bps;
197 }
198 
199 void
201 {
203  m_tInterframeGap = t;
204 }
205 
206 bool
208 {
209  NS_LOG_FUNCTION (this << p);
210  NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
211 
212  //
213  // This function is called to start the process of transmitting a packet.
214  // We need to tell the channel that we've started wiggling the wire and
215  // schedule an event that will be executed when the transmission is complete.
216  //
217  NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit");
219  m_currentPkt = p;
220  m_phyTxBeginTrace (m_currentPkt);
221 
222  Time txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ()));
223  Time txCompleteTime = txTime + m_tInterframeGap;
224 
225  NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << txCompleteTime.GetSeconds () << "sec");
227 
228  bool result = m_channel->TransmitStart (p, this, txTime);
229  if (result == false)
230  {
231  m_phyTxDropTrace (p);
232  }
233  return result;
234 }
235 
236 void
238 {
240 
241  //
242  // This function is called to when we're all done transmitting a packet.
243  // We try and pull another packet off of the transmit queue. If the queue
244  // is empty, we are done, otherwise we need to start transmitting the
245  // next packet.
246  //
247  NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
249 
250  NS_ASSERT_MSG (m_currentPkt != 0, "PointToPointNetDevice::TransmitComplete(): m_currentPkt zero");
251 
252  m_phyTxEndTrace (m_currentPkt);
253  m_currentPkt = 0;
254 
255  Ptr<Packet> p = m_queue->Dequeue ();
256  if (p == 0)
257  {
258  //
259  // No packet was on the queue, so we just exit.
260  //
261  return;
262  }
263 
264  //
265  // Got another packet off of the queue, so start the transmit process agin.
266  //
267  m_snifferTrace (p);
269  TransmitStart (p);
270 }
271 
272 bool
274 {
275  NS_LOG_FUNCTION (this << &ch);
276 
277  m_channel = ch;
278 
279  m_channel->Attach (this);
280 
281  //
282  // This device is up whenever it is attached to a channel. A better plan
283  // would be to have the link come up when both devices are attached, but this
284  // is not done for now.
285  //
286  NotifyLinkUp ();
287  return true;
288 }
289 
290 void
292 {
293  NS_LOG_FUNCTION (this << q);
294  m_queue = q;
295 }
296 
297 void
299 {
300  NS_LOG_FUNCTION (this << em);
301  m_receiveErrorModel = em;
302 }
303 
304 void
306 {
307  NS_LOG_FUNCTION (this << packet);
308  uint16_t protocol = 0;
309 
310  if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
311  {
312  //
313  // If we have an error model and it indicates that it is time to lose a
314  // corrupted packet, don't forward this packet up, let it go.
315  //
316  m_phyRxDropTrace (packet);
317  }
318  else
319  {
320  //
321  // Hit the trace hooks. All of these hooks are in the same place in this
322  // device becuase it is so simple, but this is not usually the case in
323  // more complicated devices.
324  //
325  m_snifferTrace (packet);
326  m_promiscSnifferTrace (packet);
327  m_phyRxEndTrace (packet);
328 
329  //
330  // Strip off the point-to-point protocol header and forward this packet
331  // up the protocol stack. Since this is a simple point-to-point link,
332  // there is no difference in what the promisc callback sees and what the
333  // normal receive callback sees.
334  //
335  ProcessHeader (packet, protocol);
336 
337  if (!m_promiscCallback.IsNull ())
338  {
339  m_macPromiscRxTrace (packet);
340  m_promiscCallback (this, packet, protocol, GetRemote (), GetAddress (), NetDevice::PACKET_HOST);
341  }
342 
343  m_macRxTrace (packet);
344  m_rxCallback (this, packet, protocol, GetRemote ());
345  }
346 }
347 
350 {
352  return m_queue;
353 }
354 
355 void
356 PointToPointNetDevice::NotifyLinkUp (void)
357 {
358  m_linkUp = true;
359  m_linkChangeCallbacks ();
360 }
361 
362 void
363 PointToPointNetDevice::SetIfIndex (const uint32_t index)
364 {
365  m_ifIndex = index;
366 }
367 
368 uint32_t
370 {
371  return m_ifIndex;
372 }
373 
376 {
377  return m_channel;
378 }
379 
380 //
381 // This is a point-to-point device, so we really don't need any kind of address
382 // information. However, the base class NetDevice wants us to define the
383 // methods to get and set the address. Rather than be rude and assert, we let
384 // clients get and set the address, but simply ignore them.
385 
386 void
388 {
389  m_address = Mac48Address::ConvertFrom (address);
390 }
391 
392 Address
394 {
395  return m_address;
396 }
397 
398 bool
400 {
401  return m_linkUp;
402 }
403 
404 void
406 {
407  m_linkChangeCallbacks.ConnectWithoutContext (callback);
408 }
409 
410 //
411 // This is a point-to-point device, so every transmission is a broadcast to
412 // all of the devices on the network.
413 //
414 bool
416 {
417  return true;
418 }
419 
420 //
421 // We don't really need any addressing information since this is a
422 // point-to-point device. The base class NetDevice wants us to return a
423 // broadcast address, so we make up something reasonable.
424 //
425 Address
427 {
428  return Mac48Address ("ff:ff:ff:ff:ff:ff");
429 }
430 
431 bool
433 {
434  return true;
435 }
436 
437 Address
439 {
440  return Mac48Address ("01:00:5e:00:00:00");
441 }
442 
443 Address
445 {
446  NS_LOG_FUNCTION (this << addr);
447  return Mac48Address ("33:33:00:00:00:00");
448 }
449 
450 bool
452 {
453  return true;
454 }
455 
456 bool
458 {
459  return false;
460 }
461 
462 bool
464  Ptr<Packet> packet,
465  const Address &dest,
466  uint16_t protocolNumber)
467 {
469  NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest);
470  NS_LOG_LOGIC ("UID is " << packet->GetUid ());
471 
472  //
473  // If IsLinkUp() is false it means there is no channel to send any packet
474  // over so we just hit the drop trace on the packet and return an error.
475  //
476  if (IsLinkUp () == false)
477  {
478  m_macTxDropTrace (packet);
479  return false;
480  }
481 
482  //
483  // Stick a point to point protocol header on the packet in preparation for
484  // shoving it out the door.
485  //
486  AddHeader (packet, protocolNumber);
487 
488  m_macTxTrace (packet);
489 
490  //
491  // If there's a transmission in progress, we enque the packet for later
492  // transmission; otherwise we send it now.
493  //
494  if (m_txMachineState == READY)
495  {
496  //
497  // Even if the transmitter is immediately available, we still enqueue and
498  // dequeue the packet to hit the tracing hooks.
499  //
500  if (m_queue->Enqueue (packet) == true)
501  {
502  packet = m_queue->Dequeue ();
503  m_snifferTrace (packet);
504  m_promiscSnifferTrace (packet);
505  return TransmitStart (packet);
506  }
507  else
508  {
509  // Enqueue may fail (overflow)
510  m_macTxDropTrace (packet);
511  return false;
512  }
513  }
514  else
515  {
516  return m_queue->Enqueue (packet);
517  }
518 }
519 
520 bool
522  const Address &source,
523  const Address &dest,
524  uint16_t protocolNumber)
525 {
526  return false;
527 }
528 
529 Ptr<Node>
531 {
532  return m_node;
533 }
534 
535 void
537 {
538  m_node = node;
539 }
540 
541 bool
543 {
544  return false;
545 }
546 
547 void
549 {
550  m_rxCallback = cb;
551 }
552 
553 void
555 {
556  m_promiscCallback = cb;
557 }
558 
559 bool
561 {
562  return false;
563 }
564 
565 void
566 PointToPointNetDevice::DoMpiReceive (Ptr<Packet> p)
567 {
568  Receive (p);
569 }
570 
571 Address
573 {
574  NS_ASSERT (m_channel->GetNDevices () == 2);
575  for (uint32_t i = 0; i < m_channel->GetNDevices (); ++i)
576  {
577  Ptr<NetDevice> tmp = m_channel->GetDevice (i);
578  if (tmp != this)
579  {
580  return tmp->GetAddress ();
581  }
582  }
583  NS_ASSERT (false);
584  // quiet compiler.
585  return Address ();
586 }
587 
588 bool
590 {
591  NS_LOG_FUNCTION (this << mtu);
592  m_mtu = mtu;
593  return true;
594 }
595 
596 uint16_t
598 {
600  return m_mtu;
601 }
602 
603 uint16_t
605 {
606  switch(proto)
607  {
608  case 0x0021: return 0x0800; //IPv4
609  case 0x0057: return 0x86DD; //IPv6
610  default: NS_ASSERT_MSG (false, "PPP Protocol number not defined!");
611  }
612  return 0;
613 }
614 
615 uint16_t
617 {
618  switch(proto)
619  {
620  case 0x0800: return 0x0021; //IPv4
621  case 0x86DD: return 0x0057; //IPv6
622  default: NS_ASSERT_MSG (false, "PPP Protocol number not defined!");
623  }
624  return 0;
625 }
626 
627 
628 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
void SetReceiveErrorModel(Ptr< ErrorModel > em)
keep track of time unit.
Definition: nstime.h:149
virtual bool IsLinkUp(void) const
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Ptr< Queue > GetQueue(void) const
TracedCallback< Ptr< const Packet > > m_phyTxDropTrace
virtual bool SupportsSendFrom(void) const
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
TracedCallback< Ptr< const Packet > > m_phyRxDropTrace
uint64_t GetUid(void) const
Definition: packet.cc:412
#define NS_ASSERT(condition)
Definition: assert.h:64
TracedCallback< Ptr< const Packet > > m_phyTxBeginTrace
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
static uint16_t EtherToPpp(uint16_t protocol)
Ethernet to PPP protocol number mapping.
uint32_t GetSize(void) const
Definition: packet.h:620
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
virtual Ptr< Node > GetNode(void) const
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
TracedCallback< Ptr< const Packet > > m_macRxTrace
bool ProcessHeader(Ptr< Packet > p, uint16_t &param)
a polymophic address class
Definition: address.h:86
Packet header for PPP.
Definition: ppp-header.h:48
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
static uint16_t PppToEther(uint16_t protocol)
PPP to Ethernet protocol number mapping.
Class for representing data rates.
Definition: data-rate.h:71
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
double GetSeconds(void) const
Definition: nstime.h:262
double CalculateTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:229
virtual void SetPromiscReceiveCallback(PromiscReceiveCallback cb)
void SetProtocol(uint16_t protocol)
Set the protocol type carried by this PPP packet.
Definition: ppp-header.cc:95
virtual void SetAddress(Address address)
TracedCallback< Ptr< const Packet > > m_snifferTrace
uint16_t GetProtocol(void)
Get the protocol type carried by this PPP packet.
Definition: ppp-header.cc:101
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual void AddLinkChangeCallback(Callback< void > callback)
static Mac48Address ConvertFrom(const Address &address)
virtual bool NeedsArp(void) const
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
virtual uint32_t GetIfIndex(void) const
virtual Ptr< Channel > GetChannel(void) const
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
virtual Address GetAddress(void) const
an EUI-48 address
Definition: mac48-address.h:41
virtual bool IsBridge(void) const
Return true if the net device is acting as a bridge.
Ptr< PointToPointChannel > m_channel
TracedCallback< Ptr< const Packet > > m_promiscSnifferTrace
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
Describes an IPv6 address.
Definition: ipv6-address.h:44
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
void ConnectWithoutContext(const CallbackBase &callback)
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
virtual bool SetMtu(const uint16_t mtu)
virtual void SetIfIndex(const uint32_t index)
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
virtual bool IsBroadcast(void) const
bool Attach(Ptr< PointToPointChannel > ch)
virtual void SetNode(Ptr< Node > node)
void AddHeader(Ptr< Packet > p, uint16_t protocolNumber)
virtual uint16_t GetMtu(void) const
virtual bool IsMulticast(void) const
TracedCallback< Ptr< const Packet > > m_macTxTrace
virtual Address GetBroadcast(void) const
void AddHeader(const Header &header)
Definition: packet.cc:270
TracedCallback< Ptr< const Packet > > m_phyTxEndTrace