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 
25 #include "ns3/satellite-point-to-point-isl-net-device.h"
26 
27 #include "ns3/drop-tail-queue.h"
28 #include "ns3/error-model.h"
29 #include "ns3/llc-snap-header.h"
30 #include "ns3/log.h"
31 #include "ns3/mac48-address.h"
32 #include "ns3/pointer.h"
33 #include "ns3/ppp-header.h"
34 #include "ns3/satellite-ground-station-address-tag.h"
35 #include "ns3/satellite-point-to-point-isl-channel.h"
36 #include "ns3/simulator.h"
37 #include "ns3/uinteger.h"
38 
39 NS_LOG_COMPONENT_DEFINE("PointToPointIslNetDevice");
40 
41 namespace ns3
42 {
43 
44 NS_OBJECT_ENSURE_REGISTERED(PointToPointIslNetDevice);
45 
46 TypeId
48 {
49  static TypeId tid =
50  TypeId("ns3::PointToPointIslNetDevice")
51  .SetParent<NetDevice>()
52  .AddConstructor<PointToPointIslNetDevice>()
53  .AddAttribute("ReceiveErrorModel",
54  "The receiver error model used to simulate packet loss",
55  PointerValue(),
57  MakePointerChecker<ErrorModel>())
58  .AddAttribute("InterframeGap",
59  "The time to wait between packet (frame) transmissions",
60  TimeValue(Seconds(0.0)),
62  MakeTimeChecker())
63  .AddTraceSource(
64  "PacketDropRateTrace",
65  "A packet has been dropped or not",
66  MakeTraceSourceAccessor(&PointToPointIslNetDevice::m_packetDropRateTrace),
67  "ns3::SatTypedefs::PacketDropRateTrace");
68  return tid;
69 }
70 
72  : m_txMachineState(READY),
73  m_channel(0),
74  m_linkUp(false),
75  m_currentPkt(0)
76 {
77  NS_LOG_FUNCTION(this);
78 }
79 
81 {
82  NS_LOG_FUNCTION(this);
83 }
84 
85 void
86 PointToPointIslNetDevice::AddHeader(Ptr<Packet> p, uint16_t protocolNumber)
87 {
88  NS_LOG_FUNCTION(this << p << protocolNumber);
89  PppHeader ppp;
90  ppp.SetProtocol(EtherToPpp(protocolNumber));
91  p->AddHeader(ppp);
92 }
93 
94 bool
95 PointToPointIslNetDevice::ProcessHeader(Ptr<Packet> p, uint16_t& param)
96 {
97  NS_LOG_FUNCTION(this << p << param);
98  PppHeader ppp;
99  p->RemoveHeader(ppp);
100  param = PppToEther(ppp.GetProtocol());
101  return true;
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION(this);
108  m_node = 0;
109  m_channel = 0;
111  m_currentPkt = 0;
112  m_queue = 0;
113  NetDevice::DoDispose();
114 }
115 
116 void
118 {
119  NS_LOG_FUNCTION(this);
120  m_dataRate = bps;
121 }
122 
123 void
125 {
126  NS_LOG_FUNCTION(this << t.GetSeconds());
127  m_tInterframeGap = t;
128 }
129 
130 bool
132 {
133  NS_LOG_FUNCTION(this << p);
134  NS_LOG_LOGIC("UID is " << p->GetUid() << ")");
135 
136  //
137  // This function is called to start the process of transmitting a packet.
138  // We need to tell the channel that we've started wiggling the wire and
139  // schedule an event that will be executed when the transmission is complete.
140  //
141  NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
143  m_currentPkt = p;
144 
145  Time txTime = m_dataRate.CalculateBytesTxTime(p->GetSize());
146  Time txCompleteTime = txTime + m_tInterframeGap;
147 
148  NS_LOG_LOGIC("Schedule TransmitCompleteEvent in " << txCompleteTime.GetSeconds() << "sec");
149  Simulator::Schedule(txCompleteTime, &PointToPointIslNetDevice::TransmitComplete, this);
150 
151  bool result = m_channel->TransmitStart(p, this, m_destinationNode, txTime);
152  return result;
153 }
154 
155 void
157 {
158  NS_LOG_FUNCTION(this);
159 
160  //
161  // This function is called to when we're all done transmitting a packet.
162  // We try and pull another packet off of the transmit queue. If the queue
163  // is empty, we are done, otherwise we need to start transmitting the
164  // next packet.
165  //
166  NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
168 
169  NS_ASSERT_MSG(m_currentPkt != nullptr,
170  "PointToPointIslNetDevice::TransmitComplete(): m_currentPkt zero");
171 
172  m_currentPkt = nullptr;
173 
174  Ptr<Packet> p = m_queue->Dequeue();
175  if (p == nullptr)
176  {
177  NS_LOG_LOGIC("No pending packets in device queue after tx complete");
178  return;
179  }
180 
181  TransmitStart(p);
182 }
183 
184 bool
185 PointToPointIslNetDevice::Attach(Ptr<PointToPointIslChannel> ch)
186 {
187  NS_LOG_FUNCTION(this << &ch);
188 
189  m_channel = ch;
190 
191  m_channel->Attach(this);
192 
193  //
194  // This device is up whenever it is attached to a channel. A better plan
195  // would be to have the link come up when both devices are attached, but this
196  // is not done for now.
197  //
198  NotifyLinkUp();
199  return true;
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION(this << q);
206  m_queue = q;
207 }
208 
209 void
211 {
212  NS_LOG_FUNCTION(this << em);
213  m_receiveErrorModel = em;
214 }
215 
216 void
218 {
219  NS_LOG_FUNCTION(this << packet);
220  uint16_t protocol = 0;
221 
222  if (!m_receiveErrorModel || !m_receiveErrorModel->IsCorrupt(packet))
223  {
224  //
225  // Strip off the point-to-point protocol header and forward this packet
226  // up the protocol stack. Since this is a simple point-to-point link,
227  // there is no difference in what the promisc callback sees and what the
228  // normal receive callback sees.
229  //
230  ProcessHeader(packet, protocol);
231 
232  if (!m_promiscCallback.IsNull())
233  {
234  m_promiscCallback(this,
235  packet,
236  protocol,
237  GetRemote(),
238  GetAddress(),
239  NetDevice::PACKET_HOST);
240  }
241 
242  // m_rxCallback (this, packet, protocol, GetRemote ());
243  SatGroundStationAddressTag groundStationAddressTag;
244  if (!packet->PeekPacketTag(groundStationAddressTag))
245  {
246  NS_FATAL_ERROR("SatGroundStationAddressTag not found");
247  }
248 
249  m_geoNetDevice->ReceiveFromIsl(packet, groundStationAddressTag.GetGroundStationAddress());
250  }
251 }
252 
253 void
254 PointToPointIslNetDevice::SetGeoNetDevice(Ptr<SatGeoNetDevice> geoNetDevice)
255 {
256  NS_LOG_FUNCTION(this);
257 
258  m_geoNetDevice = geoNetDevice;
259 }
260 
261 Ptr<DropTailQueue<Packet>>
263 {
264  NS_LOG_FUNCTION(this);
265  return m_queue;
266 }
267 
268 void
270 {
271  NS_LOG_FUNCTION(this);
272  m_linkUp = true;
273 }
274 
275 void
277 {
278  NS_LOG_FUNCTION(this);
279  m_ifIndex = index;
280 }
281 
282 uint32_t
284 {
285  return m_ifIndex;
286 }
287 
288 Ptr<Channel>
290 {
291  return m_channel;
292 }
293 
294 //
295 // This is a point-to-point device, so we really don't need any kind of address
296 // information. However, the base class NetDevice wants us to define the
297 // methods to get and set the address. Rather than be rude and assert, we let
298 // clients get and set the address, but simply ignore them.
299 
300 void
302 {
303  NS_LOG_FUNCTION(this << address);
304  m_address = Mac48Address::ConvertFrom(address);
305 }
306 
307 Address
309 {
310  return m_address;
311 }
312 
313 void
315 {
316  NS_LOG_FUNCTION(this << node);
317  m_destinationNode = node;
318 }
319 
320 Ptr<Node>
322 {
323  return m_destinationNode;
324 }
325 
326 bool
328 {
329  NS_LOG_FUNCTION(this);
330  return m_linkUp;
331 }
332 
333 void
335 {
336  NS_LOG_FUNCTION(this);
337 }
338 
339 //
340 // This is a point-to-point device, so every transmission is a broadcast to
341 // all of the devices on the network.
342 //
343 bool
345 {
346  NS_LOG_FUNCTION(this);
347  return true;
348 }
349 
350 //
351 // We don't really need any addressing information since this is a
352 // point-to-point device. The base class NetDevice wants us to return a
353 // broadcast address, so we make up something reasonable.
354 //
355 Address
357 {
358  NS_LOG_FUNCTION(this);
359  return Mac48Address("ff:ff:ff:ff:ff:ff");
360 }
361 
362 bool
364 {
365  NS_LOG_FUNCTION(this);
366  return true;
367 }
368 
369 Address
370 PointToPointIslNetDevice::GetMulticast(Ipv4Address multicastGroup) const
371 {
372  NS_LOG_FUNCTION(this);
373  return Mac48Address("01:00:5e:00:00:00");
374 }
375 
376 Address
378 {
379  NS_LOG_FUNCTION(this << addr);
380  return Mac48Address("33:33:00:00:00:00");
381 }
382 
383 bool
385 {
386  NS_LOG_FUNCTION(this);
387  return true;
388 }
389 
390 bool
392 {
393  NS_LOG_FUNCTION(this);
394  return false;
395 }
396 
397 bool
398 PointToPointIslNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
399 {
400  NS_LOG_FUNCTION(this << packet << dest << protocolNumber);
401  NS_LOG_LOGIC("p=" << packet << ", dest=" << &dest);
402  NS_LOG_LOGIC("UID is " << packet->GetUid());
403 
404  // If IsLinkUp() is false it means there is no channel to send any packet
405  // over so we just return an error.
406  if (IsLinkUp() == false)
407  {
408  return false;
409  }
410 
411  AddHeader(packet, protocolNumber);
412 
413  NS_ASSERT(m_queue != nullptr);
414 
415  if (m_queue->Enqueue(packet))
416  {
417  // Packet is enqued
419 
420  // If the channel is ready for transition we send the packet right now
421  if (m_txMachineState == READY)
422  {
423  packet = m_queue->Dequeue();
424  bool ret = TransmitStart(packet);
425  return ret;
426  }
427  return true;
428  }
429 
430  // Packet is dropped
432 
433  return false;
434 }
435 
436 bool
438  const Address& source,
439  const Address& dest,
440  uint16_t protocolNumber)
441 {
442  NS_LOG_FUNCTION(this << packet << source << dest << protocolNumber);
443  return false;
444 }
445 
446 Ptr<Node>
448 {
449  return m_node;
450 }
451 
452 void
454 {
455  NS_LOG_FUNCTION(this);
456  m_node = node;
457 }
458 
459 bool
461 {
462  NS_LOG_FUNCTION(this);
463  return false;
464 }
465 
466 void
467 PointToPointIslNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
468 {
469  m_rxCallback = cb;
470 }
471 
472 void
473 PointToPointIslNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
474 {
475  m_promiscCallback = cb;
476 }
477 
478 bool
480 {
481  NS_LOG_FUNCTION(this);
482  return false;
483 }
484 
485 Address
487 {
488  NS_LOG_FUNCTION(this);
489  NS_ASSERT(m_channel->GetNDevices() == 2);
490  for (std::size_t i = 0; i < m_channel->GetNDevices(); ++i)
491  {
492  Ptr<NetDevice> tmp = m_channel->GetDevice(i);
493  if (tmp != this)
494  {
495  return tmp->GetAddress();
496  }
497  }
498  NS_ASSERT(false);
499  // quiet compiler.
500  return Address();
501 }
502 
503 bool
505 {
506  NS_LOG_FUNCTION(this << mtu);
507  m_mtu = mtu;
508  return true;
509 }
510 
511 uint16_t
513 {
514  NS_LOG_FUNCTION(this);
515  return m_mtu;
516 }
517 
518 uint16_t
520 {
521  NS_LOG_FUNCTION_NOARGS();
522  switch (proto)
523  {
524  case 0x0021:
525  return 0x0800; // IPv4
526  case 0x0057:
527  return 0x86DD; // IPv6
528  default:
529  NS_ASSERT_MSG(false, "PPP Protocol number not defined!");
530  }
531  return 0;
532 }
533 
534 uint16_t
536 {
537  NS_LOG_FUNCTION_NOARGS();
538  switch (proto)
539  {
540  case 0x0800:
541  return 0x0021; // IPv4
542  case 0x86DD:
543  return 0x0057; // IPv6
544  default:
545  NS_ASSERT_MSG(false, "PPP Protocol number not defined!");
546  }
547  return 0;
548 }
549 
550 } // 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)
void SetGeoNetDevice(Ptr< SatGeoNetDevice > geoNetDevice)
Set the associated GeoNetDevice.
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.
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Ptr< SatGeoNetDevice > m_geoNetDevice
Satellite GEO Net Device associated to this instance.
void TransmitComplete(void)
Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
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.