satellite-point-to-point-isl-net-device.cc
Go to the documentation of this file.
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  * (Based on point-to-point network device)
19  * Author: Andre Aguas March 2020
20  * Simon 2020
21  * Adapted to SNS-3 by: Bastien Tauran <bastien.tauran@viveris.fr>
22  *
23  */
24 
26 
29 
30 #include "ns3/drop-tail-queue.h"
31 #include "ns3/error-model.h"
32 #include "ns3/llc-snap-header.h"
33 #include "ns3/log.h"
34 #include "ns3/mac48-address.h"
35 #include "ns3/pointer.h"
36 #include "ns3/ppp-header.h"
37 #include "ns3/simulator.h"
38 #include "ns3/uinteger.h"
39 
40 #include <cstddef>
41 
42 NS_LOG_COMPONENT_DEFINE("PointToPointIslNetDevice");
43 
44 namespace ns3
45 {
46 
47 NS_OBJECT_ENSURE_REGISTERED(PointToPointIslNetDevice);
48 
49 TypeId
51 {
52  static TypeId tid =
53  TypeId("ns3::PointToPointIslNetDevice")
54  .SetParent<NetDevice>()
55  .AddConstructor<PointToPointIslNetDevice>()
56  .AddAttribute("ReceiveErrorModel",
57  "The receiver error model used to simulate packet loss",
58  PointerValue(),
60  MakePointerChecker<ErrorModel>())
61  .AddAttribute("InterframeGap",
62  "The time to wait between packet (frame) transmissions",
63  TimeValue(Seconds(0.0)),
65  MakeTimeChecker())
66  .AddTraceSource(
67  "PacketDropRateTrace",
68  "A packet has been dropped or not",
69  MakeTraceSourceAccessor(&PointToPointIslNetDevice::m_packetDropRateTrace),
70  "ns3::SatTypedefs::PacketDropRateTrace");
71  return tid;
72 }
73 
75  : m_txMachineState(READY),
76  m_channel(0),
77  m_linkUp(false),
78  m_currentPkt(0)
79 {
80  NS_LOG_FUNCTION(this);
81 }
82 
84 {
85  NS_LOG_FUNCTION(this);
86 }
87 
88 void
89 PointToPointIslNetDevice::AddHeader(Ptr<Packet> p, uint16_t protocolNumber)
90 {
91  NS_LOG_FUNCTION(this << p << protocolNumber);
92  PppHeader ppp;
93  ppp.SetProtocol(EtherToPpp(protocolNumber));
94  p->AddHeader(ppp);
95 }
96 
97 bool
98 PointToPointIslNetDevice::ProcessHeader(Ptr<Packet> p, uint16_t& param)
99 {
100  NS_LOG_FUNCTION(this << p << param);
101  PppHeader ppp;
102  p->RemoveHeader(ppp);
103  param = PppToEther(ppp.GetProtocol());
104  return true;
105 }
106 
107 void
109 {
110  NS_LOG_FUNCTION(this);
111  m_node = 0;
112  m_channel = 0;
114  m_currentPkt = 0;
115  m_queue = 0;
116  NetDevice::DoDispose();
117 }
118 
119 void
121 {
122  NS_LOG_FUNCTION(this);
123  m_dataRate = bps;
124 }
125 
126 void
128 {
129  NS_LOG_FUNCTION(this << t.GetSeconds());
130  m_tInterframeGap = t;
131 }
132 
133 bool
135 {
136  NS_LOG_FUNCTION(this << p);
137  NS_LOG_LOGIC("UID is " << p->GetUid() << ")");
138 
139  //
140  // This function is called to start the process of transmitting a packet.
141  // We need to tell the channel that we've started wiggling the wire and
142  // schedule an event that will be executed when the transmission is complete.
143  //
144  NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
146  m_currentPkt = p;
147 
148  Time txTime = m_dataRate.CalculateBytesTxTime(p->GetSize());
149  Time txCompleteTime = txTime + m_tInterframeGap;
150 
151  NS_LOG_LOGIC("Schedule TransmitCompleteEvent in " << txCompleteTime.GetSeconds() << "sec");
152  Simulator::Schedule(txCompleteTime, &PointToPointIslNetDevice::TransmitComplete, this);
153 
154  bool result = m_channel->TransmitStart(p, this, m_destinationNode, txTime);
155  return result;
156 }
157 
158 void
160 {
161  NS_LOG_FUNCTION(this);
162 
163  //
164  // This function is called to when we're all done transmitting a packet.
165  // We try and pull another packet off of the transmit queue. If the queue
166  // is empty, we are done, otherwise we need to start transmitting the
167  // next packet.
168  //
169  NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
171 
172  NS_ASSERT_MSG(m_currentPkt != nullptr,
173  "PointToPointIslNetDevice::TransmitComplete(): m_currentPkt zero");
174 
175  m_currentPkt = nullptr;
176 
177  Ptr<Packet> p = m_queue->Dequeue();
178  if (p == nullptr)
179  {
180  NS_LOG_LOGIC("No pending packets in device queue after tx complete");
181  return;
182  }
183 
184  TransmitStart(p);
185 }
186 
187 bool
188 PointToPointIslNetDevice::Attach(Ptr<PointToPointIslChannel> ch)
189 {
190  NS_LOG_FUNCTION(this << &ch);
191 
192  m_channel = ch;
193 
194  m_channel->Attach(this);
195 
196  //
197  // This device is up whenever it is attached to a channel. A better plan
198  // would be to have the link come up when both devices are attached, but this
199  // is not done for now.
200  //
201  NotifyLinkUp();
202  return true;
203 }
204 
205 void
207 {
208  NS_LOG_FUNCTION(this << q);
209  m_queue = q;
210 }
211 
212 void
214 {
215  NS_LOG_FUNCTION(this << em);
216  m_receiveErrorModel = em;
217 }
218 
219 void
221 {
222  NS_LOG_FUNCTION(this << packet);
223  uint16_t protocol = 0;
224 
225  if (!m_receiveErrorModel || !m_receiveErrorModel->IsCorrupt(packet))
226  {
227  //
228  // Strip off the point-to-point protocol header and forward this packet
229  // up the protocol stack. Since this is a simple point-to-point link,
230  // there is no difference in what the promisc callback sees and what the
231  // normal receive callback sees.
232  //
233  ProcessHeader(packet, protocol);
234 
235  if (!m_promiscCallback.IsNull())
236  {
237  m_promiscCallback(this,
238  packet,
239  protocol,
240  GetRemote(),
241  GetAddress(),
242  NetDevice::PACKET_HOST);
243  }
244 
245  // m_rxCallback (this, packet, protocol, GetRemote ());
246  SatGroundStationAddressTag groundStationAddressTag;
247  if (!packet->PeekPacketTag(groundStationAddressTag))
248  {
249  NS_FATAL_ERROR("SatGroundStationAddressTag not found");
250  }
251 
252  m_orbiterNetDevice->ReceiveFromIsl(packet,
253  groundStationAddressTag.GetGroundStationAddress());
254  }
255 }
256 
257 void
258 PointToPointIslNetDevice::SetOrbiterNetDevice(Ptr<SatOrbiterNetDevice> orbiterNetDevice)
259 {
260  NS_LOG_FUNCTION(this);
261 
262  m_orbiterNetDevice = orbiterNetDevice;
263 }
264 
265 Ptr<DropTailQueue<Packet>>
267 {
268  NS_LOG_FUNCTION(this);
269  return m_queue;
270 }
271 
272 void
274 {
275  NS_LOG_FUNCTION(this);
276  m_linkUp = true;
277 }
278 
279 void
281 {
282  NS_LOG_FUNCTION(this);
283  m_ifIndex = index;
284 }
285 
286 uint32_t
288 {
289  return m_ifIndex;
290 }
291 
292 Ptr<Channel>
294 {
295  return m_channel;
296 }
297 
298 //
299 // This is a point-to-point device, so we really don't need any kind of address
300 // information. However, the base class NetDevice wants us to define the
301 // methods to get and set the address. Rather than be rude and assert, we let
302 // clients get and set the address, but simply ignore them.
303 
304 void
306 {
307  NS_LOG_FUNCTION(this << address);
308  m_address = Mac48Address::ConvertFrom(address);
309 }
310 
311 Address
313 {
314  return m_address;
315 }
316 
317 void
319 {
320  NS_LOG_FUNCTION(this << node);
321  m_destinationNode = node;
322 }
323 
324 Ptr<Node>
326 {
327  return m_destinationNode;
328 }
329 
330 bool
332 {
333  NS_LOG_FUNCTION(this);
334  return m_linkUp;
335 }
336 
337 void
339 {
340  NS_LOG_FUNCTION(this);
341 }
342 
343 //
344 // This is a point-to-point device, so every transmission is a broadcast to
345 // all of the devices on the network.
346 //
347 bool
349 {
350  NS_LOG_FUNCTION(this);
351  return true;
352 }
353 
354 //
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.
358 //
359 Address
361 {
362  NS_LOG_FUNCTION(this);
363  return Mac48Address("ff:ff:ff:ff:ff:ff");
364 }
365 
366 bool
368 {
369  NS_LOG_FUNCTION(this);
370  return true;
371 }
372 
373 Address
374 PointToPointIslNetDevice::GetMulticast(Ipv4Address multicastGroup) const
375 {
376  NS_LOG_FUNCTION(this);
377  return Mac48Address("01:00:5e:00:00:00");
378 }
379 
380 Address
382 {
383  NS_LOG_FUNCTION(this << addr);
384  return Mac48Address("33:33:00:00:00:00");
385 }
386 
387 bool
389 {
390  NS_LOG_FUNCTION(this);
391  return true;
392 }
393 
394 bool
396 {
397  NS_LOG_FUNCTION(this);
398  return false;
399 }
400 
401 bool
402 PointToPointIslNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
403 {
404  NS_LOG_FUNCTION(this << packet << dest << protocolNumber);
405  NS_LOG_LOGIC("p=" << packet << ", dest=" << &dest);
406  NS_LOG_LOGIC("UID is " << packet->GetUid());
407 
408  // If IsLinkUp() is false it means there is no channel to send any packet
409  // over so we just return an error.
410  if (IsLinkUp() == false)
411  {
412  return false;
413  }
414 
415  AddHeader(packet, protocolNumber);
416 
417  NS_ASSERT(m_queue != nullptr);
418 
419  if (m_queue->Enqueue(packet))
420  {
421  // Packet is enqued
423 
424  // If the channel is ready for transition we send the packet right now
425  if (m_txMachineState == READY)
426  {
427  packet = m_queue->Dequeue();
428  bool ret = TransmitStart(packet);
429  return ret;
430  }
431  return true;
432  }
433 
434  // Packet is dropped
436 
437  return false;
438 }
439 
440 bool
442  const Address& source,
443  const Address& dest,
444  uint16_t protocolNumber)
445 {
446  NS_LOG_FUNCTION(this << packet << source << dest << protocolNumber);
447  return false;
448 }
449 
450 Ptr<Node>
452 {
453  return m_node;
454 }
455 
456 void
458 {
459  NS_LOG_FUNCTION(this);
460  m_node = node;
461 }
462 
463 bool
465 {
466  NS_LOG_FUNCTION(this);
467  return false;
468 }
469 
470 void
471 PointToPointIslNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
472 {
473  m_rxCallback = cb;
474 }
475 
476 void
477 PointToPointIslNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
478 {
479  m_promiscCallback = cb;
480 }
481 
482 bool
484 {
485  NS_LOG_FUNCTION(this);
486  return false;
487 }
488 
489 Address
491 {
492  NS_LOG_FUNCTION(this);
493  NS_ASSERT(m_channel->GetNDevices() == 2);
494  for (std::size_t i = 0; i < m_channel->GetNDevices(); ++i)
495  {
496  Ptr<NetDevice> tmp = m_channel->GetDevice(i);
497  if (tmp != this)
498  {
499  return tmp->GetAddress();
500  }
501  }
502  NS_ASSERT(false);
503  // quiet compiler.
504  return Address();
505 }
506 
507 bool
509 {
510  NS_LOG_FUNCTION(this << mtu);
511  m_mtu = mtu;
512  return true;
513 }
514 
515 uint16_t
517 {
518  NS_LOG_FUNCTION(this);
519  return m_mtu;
520 }
521 
522 uint16_t
524 {
525  NS_LOG_FUNCTION_NOARGS();
526  switch (proto)
527  {
528  case 0x0021:
529  return 0x0800; // IPv4
530  case 0x0057:
531  return 0x86DD; // IPv6
532  default:
533  NS_ASSERT_MSG(false, "PPP Protocol number not defined!");
534  }
535  return 0;
536 }
537 
538 uint16_t
540 {
541  NS_LOG_FUNCTION_NOARGS();
542  switch (proto)
543  {
544  case 0x0800:
545  return 0x0021; // IPv4
546  case 0x86DD:
547  return 0x0057; // IPv6
548  default:
549  NS_ASSERT_MSG(false, "PPP Protocol number not defined!");
550  }
551  return 0;
552 }
553 
554 } // namespace ns3
@ READY
The transmitter is ready to begin transmission of a packet.
@ BUSY
The transmitter is busy transmitting a packet.
Ptr< DropTailQueue< Packet > > m_queue
The Queue which this PointToPointIslNetDevice uses as a packet source.
void SetReceiveErrorModel(Ptr< ErrorModel > em)
Attach a receive ErrorModel to the PointToPointIslNetDevice.
NetDevice::ReceiveCallback m_rxCallback
Receive callback.
bool TransmitStart(Ptr< Packet > p)
Start Sending a Packet Down the Wire.
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
void NotifyLinkUp(void)
Make the link up and running.
void SetInterframeGap(Time t)
Set the interframe gap used to separate packets.
Mac48Address m_address
Mac48Address of this NetDevice.
void Receive(Ptr< Packet > p)
Receive a packet from a connected PointToPointIslChannel.
Ptr< Packet > m_currentPkt
Current packet processed.
PointToPointIslNetDevice()
Construct a PointToPointIslNetDevice.
bool ProcessHeader(Ptr< Packet > p, uint16_t &param)
Removes, from a packet of data, all headers and trailers that relate to the protocol implemented by t...
void AddHeader(Ptr< Packet > p, uint16_t protocolNumber)
Adds the necessary headers and trailers to a packet of data in order to respect the protocol implemen...
NetDevice::PromiscReceiveCallback m_promiscCallback
Receive callback.
bool m_linkUp
Identify if the link is up or not.
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
void SetDataRate(DataRate bps)
Set the Data Rate used for transmission of packets.
Ptr< DropTailQueue< Packet > > GetQueue(void) const
Get a copy of the attached Queue.
virtual void AddLinkChangeCallback(Callback< void > callback)
virtual void SetPromiscReceiveCallback(PromiscReceiveCallback cb)
TracedCallback< uint32_t, Ptr< Node >, Ptr< Node >, bool > m_packetDropRateTrace
Traced callback for drop rate in queue.
Ptr< Node > m_node
Node owning this NetDevice.
virtual ~PointToPointIslNetDevice()
Destroy a PointToPointIslNetDevice.
TxMachineState m_txMachineState
The state of the Net Device transmit state machine.
Time m_tInterframeGap
The interframe gap that the Net Device uses to throttle packet transmission.
DataRate m_dataRate
The data rate that the Net Device uses to simulate packet transmission timing.
static uint16_t EtherToPpp(uint16_t protocol)
Ethernet to PPP protocol number mapping.
Ptr< SatOrbiterNetDevice > m_orbiterNetDevice
Satellite Orbiter Net Device associated to this instance.
virtual Address GetMulticast(Ipv4Address multicastGroup) const
void TransmitComplete(void)
Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
void SetOrbiterNetDevice(Ptr< SatOrbiterNetDevice > orbiterNetDevice)
Set the associated OrbiterNetDevice.
static uint16_t PppToEther(uint16_t protocol)
PPP to Ethernet protocol number mapping.
uint32_t m_mtu
The Maximum Transmission Unit.
virtual void DoDispose(void)
Dispose of the object.
Ptr< Node > m_destinationNode
Node at the other end of the p2pIslLink.
Ptr< PointToPointIslChannel > m_channel
The PointToPointIslChannel to which this PointToPointIslNetDevice has been attached.
void SetQueue(Ptr< DropTailQueue< Packet >> queue)
Attach a queue to the PointToPointIslNetDevice.
bool Attach(Ptr< PointToPointIslChannel > ch)
Attach the device to a channel.
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
Ptr< ErrorModel > m_receiveErrorModel
Error model for receive packet events.
Tag to store ground station destination address.
Mac48Address GetGroundStationAddress(void) const
Get the ground station MAC address.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.