A Discrete-Event Network Simulator
API
csma-net-device.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Emmanuelle Laprise
3  * Copyright (c) 2012 Jeffrey Young
4  * Copyright (c) 2014 Murphy McCauley
5  * Copyright (c) 2017 Luciano Jerez Chaves
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation;
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
21  * Author: Jeff Young <jyoung9@gatech.edu>
22  * Author: Murphy McCauley <murphy.mccauley@gmail.com>
23  * Author: Luciano Jerez Chaves <ljerezchaves@gmail.com>
24  */
25 
26 #include "csma-net-device.h"
27 
28 #include "csma-channel.h"
29 
30 #include "ns3/boolean.h"
31 #include "ns3/enum.h"
32 #include "ns3/error-model.h"
33 #include "ns3/ethernet-header.h"
34 #include "ns3/ethernet-trailer.h"
35 #include "ns3/llc-snap-header.h"
36 #include "ns3/log.h"
37 #include "ns3/pointer.h"
38 #include "ns3/queue.h"
39 #include "ns3/simulator.h"
40 #include "ns3/trace-source-accessor.h"
41 #include "ns3/uinteger.h"
42 
43 namespace ns3
44 {
45 
46 NS_LOG_COMPONENT_DEFINE("CsmaNetDevice");
47 
48 NS_OBJECT_ENSURE_REGISTERED(CsmaNetDevice);
49 
50 TypeId
52 {
53  static TypeId tid =
54  TypeId("ns3::CsmaNetDevice")
56  .SetGroupName("Csma")
57  .AddConstructor<CsmaNetDevice>()
58  .AddAttribute("Address",
59  "The MAC address of this device.",
60  Mac48AddressValue(Mac48Address("ff:ff:ff:ff:ff:ff")),
61  MakeMac48AddressAccessor(&CsmaNetDevice::m_address),
62  MakeMac48AddressChecker())
63  .AddAttribute("Mtu",
64  "The MAC-level Maximum Transmission Unit",
67  MakeUintegerChecker<uint16_t>())
68  .AddAttribute("EncapsulationMode",
69  "The link-layer encapsulation type to use.",
70  EnumValue(DIX),
72  MakeEnumChecker(DIX, "Dix", LLC, "Llc"))
73  .AddAttribute("SendEnable",
74  "Enable or disable the transmitter section of the device.",
75  BooleanValue(true),
78  .AddAttribute("ReceiveEnable",
79  "Enable or disable the receiver section of the device.",
80  BooleanValue(true),
83  .AddAttribute("ReceiveErrorModel",
84  "The receiver error model used to simulate packet loss",
85  PointerValue(),
87  MakePointerChecker<ErrorModel>())
88 
89  //
90  // Transmit queueing discipline for the device which includes its own set
91  // of trace hooks.
92  //
93  .AddAttribute("TxQueue",
94  "A queue to use as the transmit queue in the device.",
95  PointerValue(),
97  MakePointerChecker<Queue<Packet>>())
98 
99  //
100  // Trace sources at the "top" of the net device, where packets transition
101  // to/from higher layers.
102  //
103  .AddTraceSource("MacTx",
104  "Trace source indicating a packet has "
105  "arrived for transmission by this device",
107  "ns3::Packet::TracedCallback")
108  .AddTraceSource("MacTxDrop",
109  "Trace source indicating a packet has been "
110  "dropped by the device before transmission",
112  "ns3::Packet::TracedCallback")
113  .AddTraceSource("MacPromiscRx",
114  "A packet has been received by this device, "
115  "has been passed up from the physical layer "
116  "and is being forwarded up the local protocol stack. "
117  "This is a promiscuous trace,",
119  "ns3::Packet::TracedCallback")
120  .AddTraceSource("MacRx",
121  "A packet has been received by this device, "
122  "has been passed up from the physical layer "
123  "and is being forwarded up the local protocol stack. "
124  "This is a non-promiscuous trace,",
126  "ns3::Packet::TracedCallback")
127 #if 0
128  // Not currently implemented in this device
129  .AddTraceSource ("MacRxDrop",
130  "Trace source indicating a packet was received, "
131  "but dropped before being forwarded up the stack",
133  "ns3::Packet::TracedCallback")
134 #endif
135  .AddTraceSource("MacTxBackoff",
136  "Trace source indicating a packet has been "
137  "delayed by the CSMA backoff process",
139  "ns3::Packet::TracedCallback")
140  //
141  // Trace sources at the "bottom" of the net device, where packets transition
142  // to/from the channel.
143  //
144  .AddTraceSource("PhyTxBegin",
145  "Trace source indicating a packet has "
146  "begun transmitting over the channel",
148  "ns3::Packet::TracedCallback")
149  .AddTraceSource("PhyTxEnd",
150  "Trace source indicating a packet has been "
151  "completely transmitted over the channel",
153  "ns3::Packet::TracedCallback")
154  .AddTraceSource("PhyTxDrop",
155  "Trace source indicating a packet has been "
156  "dropped by the device during transmission",
158  "ns3::Packet::TracedCallback")
159 #if 0
160  // Not currently implemented in this device
161  .AddTraceSource ("PhyRxBegin",
162  "Trace source indicating a packet has "
163  "begun being received by the device",
165  "ns3::Packet::TracedCallback")
166 #endif
167  .AddTraceSource("PhyRxEnd",
168  "Trace source indicating a packet has been "
169  "completely received by the device",
171  "ns3::Packet::TracedCallback")
172  .AddTraceSource("PhyRxDrop",
173  "Trace source indicating a packet has been "
174  "dropped by the device during reception",
176  "ns3::Packet::TracedCallback")
177  //
178  // Trace sources designed to simulate a packet sniffer facility (tcpdump).
179  //
180  .AddTraceSource("Sniffer",
181  "Trace source simulating a non-promiscuous "
182  "packet sniffer attached to the device",
184  "ns3::Packet::TracedCallback")
185  .AddTraceSource("PromiscSniffer",
186  "Trace source simulating a promiscuous "
187  "packet sniffer attached to the device",
189  "ns3::Packet::TracedCallback");
190  return tid;
191 }
192 
194  : m_linkUp(false)
195 {
196  NS_LOG_FUNCTION(this);
199  m_channel = nullptr;
200 
201  //
202  // We would like to let the attribute system take care of initializing the
203  // packet encapsulation stuff, but we also don't want to get caught up in
204  // initialization order changes. So we'll get the three problem variables
205  // into a consistent state here before the attribute calls, and then depend
206  // on the semantics of the setters to preserve a consistent state. This
207  // really doesn't have to be the same set of values as the initial values
208  // set by the attributes, but it does have to be a consistent set. That is,
209  // you can just change the default encapsulation mode above without having
210  // to change it here.
211  //
212  m_encapMode = DIX;
213 }
214 
216 {
218  m_queue = nullptr;
219 }
220 
221 void
223 {
225  m_channel = nullptr;
226  m_node = nullptr;
227  m_queue = nullptr;
229 }
230 
231 void
233 {
234  NS_LOG_FUNCTION(mode);
235 
236  m_encapMode = mode;
237 
238  NS_LOG_LOGIC("m_encapMode = " << m_encapMode);
239  NS_LOG_LOGIC("m_mtu = " << m_mtu);
240 }
241 
244 {
246  return m_encapMode;
247 }
248 
249 bool
251 {
252  NS_LOG_FUNCTION(this << mtu);
253  m_mtu = mtu;
254 
255  NS_LOG_LOGIC("m_encapMode = " << m_encapMode);
256  NS_LOG_LOGIC("m_mtu = " << m_mtu);
257 
258  return true;
259 }
260 
261 uint16_t
263 {
265  return m_mtu;
266 }
267 
268 void
270 {
271  NS_LOG_FUNCTION(sendEnable);
272  m_sendEnable = sendEnable;
273 }
274 
275 void
277 {
278  NS_LOG_FUNCTION(receiveEnable);
279  m_receiveEnable = receiveEnable;
280 }
281 
282 bool
284 {
286  return m_sendEnable;
287 }
288 
289 bool
291 {
293  return m_receiveEnable;
294 }
295 
296 void
298 {
299  NS_LOG_FUNCTION(t);
300  m_tInterframeGap = t;
301 }
302 
303 void
305  uint32_t minSlots,
306  uint32_t maxSlots,
307  uint32_t ceiling,
308  uint32_t maxRetries)
309 {
310  NS_LOG_FUNCTION(slotTime << minSlots << maxSlots << ceiling << maxRetries);
311  m_backoff.m_slotTime = slotTime;
312  m_backoff.m_minSlots = minSlots;
313  m_backoff.m_maxSlots = maxSlots;
314  m_backoff.m_ceiling = ceiling;
315  m_backoff.m_maxRetries = maxRetries;
316 }
317 
318 void
320  Mac48Address source,
321  Mac48Address dest,
322  uint16_t protocolNumber)
323 {
324  NS_LOG_FUNCTION(p << source << dest << protocolNumber);
325 
326  EthernetHeader header(false);
327  header.SetSource(source);
328  header.SetDestination(dest);
329 
330  EthernetTrailer trailer;
331 
332  NS_LOG_LOGIC("p->GetSize () = " << p->GetSize());
333  NS_LOG_LOGIC("m_encapMode = " << m_encapMode);
334  NS_LOG_LOGIC("m_mtu = " << m_mtu);
335 
336  uint16_t lengthType = 0;
337  switch (m_encapMode)
338  {
339  case DIX:
340  NS_LOG_LOGIC("Encapsulating packet as DIX (type interpretation)");
341  //
342  // This corresponds to the type interpretation of the lengthType field as
343  // in the old Ethernet Blue Book.
344  //
345  lengthType = protocolNumber;
346 
347  //
348  // All Ethernet frames must carry a minimum payload of 46 bytes. We need
349  // to pad out if we don't have enough bytes. These must be real bytes
350  // since they will be written to pcap files and compared in regression
351  // trace files.
352  //
353  if (p->GetSize() < 46)
354  {
355  uint8_t buffer[46];
356  memset(buffer, 0, 46);
357  Ptr<Packet> padd = Create<Packet>(buffer, 46 - p->GetSize());
358  p->AddAtEnd(padd);
359  }
360  break;
361  case LLC: {
362  NS_LOG_LOGIC("Encapsulating packet as LLC (length interpretation)");
363 
364  LlcSnapHeader llc;
365  llc.SetType(protocolNumber);
366  p->AddHeader(llc);
367 
368  //
369  // This corresponds to the length interpretation of the lengthType
370  // field but with an LLC/SNAP header added to the payload as in
371  // IEEE 802.2
372  //
373  lengthType = p->GetSize();
374 
375  //
376  // All Ethernet frames must carry a minimum payload of 46 bytes. The
377  // LLC SNAP header counts as part of this payload. We need to pad out
378  // if we don't have enough bytes. These must be real bytes since they
379  // will be written to pcap files and compared in regression trace files.
380  //
381  if (p->GetSize() < 46)
382  {
383  uint8_t buffer[46];
384  memset(buffer, 0, 46);
385  Ptr<Packet> padd = Create<Packet>(buffer, 46 - p->GetSize());
386  p->AddAtEnd(padd);
387  }
388 
389  NS_ASSERT_MSG(p->GetSize() <= GetMtu(),
390  "CsmaNetDevice::AddHeader(): 802.3 Length/Type field with LLC/SNAP: "
391  "length interpretation must not exceed device frame size minus overhead");
392  }
393  break;
394  case ILLEGAL:
395  default:
396  NS_FATAL_ERROR("CsmaNetDevice::AddHeader(): Unknown packet encapsulation mode");
397  break;
398  }
399 
400  NS_LOG_LOGIC("header.SetLengthType (" << lengthType << ")");
401  header.SetLengthType(lengthType);
402  p->AddHeader(header);
403 
404  if (Node::ChecksumEnabled())
405  {
406  trailer.EnableFcs(true);
407  }
408  trailer.CalcFcs(p);
409  p->AddTrailer(trailer);
410 }
411 
412 #if 0
413 bool
414 CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
415 {
416  NS_LOG_FUNCTION (p << param);
417 
418  EthernetTrailer trailer;
419  p->RemoveTrailer (trailer);
420 
421  EthernetHeader header (false);
422  p->RemoveHeader (header);
423 
424  if ((header.GetDestination () != GetBroadcast ()) &&
425  (header.GetDestination () != GetAddress ()))
426  {
427  return false;
428  }
429 
430  switch (m_encapMode)
431  {
432  case DIX:
433  param = header.GetLengthType ();
434  break;
435  case LLC:
436  {
437  LlcSnapHeader llc;
438  p->RemoveHeader (llc);
439  param = llc.GetType ();
440  }
441  break;
442  case ILLEGAL:
443  default:
444  NS_FATAL_ERROR ("CsmaNetDevice::ProcessHeader(): Unknown packet encapsulation mode");
445  break;
446  }
447  return true;
448 }
449 #endif
450 
451 void
453 {
455 
456  //
457  // This function is called to start the process of transmitting a packet. We
458  // expect that the packet to transmit will be found in m_currentPkt.
459  //
460  NS_ASSERT_MSG(m_currentPkt, "CsmaNetDevice::TransmitStart(): m_currentPkt not set");
461 
462  NS_LOG_LOGIC("m_currentPkt = " << m_currentPkt);
463  NS_LOG_LOGIC("UID = " << m_currentPkt->GetUid());
464  NS_LOG_LOGIC("Device ID = " << m_deviceId);
465 
466  //
467  // Only transmit if the send side of net device is enabled
468  //
469  if (IsSendEnabled() == false)
470  {
472  m_currentPkt = nullptr;
473  return;
474  }
475 
476  //
477  // Somebody has called here telling us to start transmitting a packet. They
478  // can only do this if the state machine is in the READY or BACKOFF state.
479  // Specifically, if we are ready to start transmitting, we cannot already
480  // be transmitting (i.e., BUSY)
481  //
483  "Must be READY to transmit. Tx state is: " << m_txMachineState);
484 
485  //
486  // Now we sense the state of the medium. If idle, we start transmitting.
487  // Otherwise, we have to wait.
488  //
489  if (m_channel->GetState(m_deviceId) != CsmaChannel::IDLE)
490  {
491  //
492  // The (sub)channel is busy. If in half-duplex mode, backoff and
493  // reschedule TransmitStart() unless we have exhausted all of our
494  // retries. This is not supposed to happen in full-duplex mode.
495  //
496  if (m_channel->IsFullDuplex() == false)
497  {
499 
501  {
502  //
503  // Too many retries, abort transmission of packet
504  //
505  TransmitAbort();
506  }
507  else
508  {
510 
512  Time backoffTime = m_backoff.GetBackoffTime();
513 
514  NS_LOG_LOGIC("Channel busy, backing off for " << backoffTime.As(Time::S));
515 
517  }
518  }
519  }
520  else
521  {
522  //
523  // The channel is free, transmit the packet
524  //
526  if (m_channel->TransmitStart(m_currentPkt, m_deviceId) == false)
527  {
528  NS_LOG_WARN("Channel TransmitStart returns an error");
530  m_currentPkt = nullptr;
532  }
533  else
534  {
535  //
536  // Transmission succeeded, reset the backoff time parameters and
537  // schedule a transmit complete event.
538  //
541 
543  NS_LOG_LOGIC("Schedule TransmitCompleteEvent in " << tEvent.As(Time::S));
545  }
546  }
547 }
548 
549 void
551 {
553 
554  //
555  // When we started the process of transmitting the current packet, it was
556  // placed in m_currentPkt. So we had better find one there.
557  //
558  NS_ASSERT_MSG(m_currentPkt, "CsmaNetDevice::TransmitAbort(): m_currentPkt zero");
559  NS_LOG_LOGIC("m_currentPkt=" << m_currentPkt);
560  NS_LOG_LOGIC("Pkt UID is " << m_currentPkt->GetUid() << ")");
561 
563  m_currentPkt = nullptr;
564 
566  "Must be in BACKOFF state to abort. Tx state is: " << m_txMachineState);
567 
568  //
569  // We're done with that one, so reset the backoff algorithm and ready the
570  // transmit state machine.
571  //
574 
575  //
576  // If there is another packet on the input queue, we need to start trying to
577  // get that out. If the queue is empty we just wait until someone puts one
578  // in.
579  //
580  if (m_queue->IsEmpty())
581  {
582  return;
583  }
584  else
585  {
586  Ptr<Packet> packet = m_queue->Dequeue();
587  NS_ASSERT_MSG(packet,
588  "CsmaNetDevice::TransmitAbort(): IsEmpty false but no Packet on queue?");
589  m_currentPkt = packet;
592  TransmitStart();
593  }
594 }
595 
596 void
598 {
600 
601  //
602  // This function is called to finish the process of transmitting a packet.
603  // We need to tell the channel that we've stopped wiggling the wire and
604  // schedule an event that will be executed when it's time to re-enable
605  // the transmitter after the interframe gap.
606  //
608  "CsmaNetDevice::transmitCompleteEvent(): Must be BUSY if transmitting");
611 
612  //
613  // When we started transmitting the current packet, it was placed in
614  // m_currentPkt. So we had better find one there.
615  //
616  NS_ASSERT_MSG(m_currentPkt, "CsmaNetDevice::TransmitCompleteEvent(): m_currentPkt zero");
617  NS_LOG_LOGIC("m_currentPkt=" << m_currentPkt);
618  NS_LOG_LOGIC("Pkt UID is " << m_currentPkt->GetUid() << ")");
619  NS_LOG_LOGIC("Device ID is " << m_deviceId);
620 
621  m_channel->TransmitEnd(m_deviceId);
623  m_currentPkt = nullptr;
624 
625  NS_LOG_LOGIC("Schedule TransmitReadyEvent in " << m_tInterframeGap.As(Time::S));
626 
628 }
629 
630 void
632 {
634 
635  //
636  // This function is called to enable the transmitter after the interframe
637  // gap has passed. If there are pending transmissions, we use this opportunity
638  // to start the next transmit.
639  //
641  "CsmaNetDevice::TransmitReadyEvent(): Must be in interframe gap");
643 
644  //
645  // We expect that the packet we had been transmitting was cleared when the
646  // TransmitCompleteEvent() was executed.
647  //
648  NS_ASSERT_MSG(!m_currentPkt, "CsmaNetDevice::TransmitReadyEvent(): m_currentPkt nonzero");
649 
650  //
651  // Get the next packet from the queue for transmitting
652  //
653  if (m_queue->IsEmpty())
654  {
655  return;
656  }
657  else
658  {
659  Ptr<Packet> packet = m_queue->Dequeue();
660  NS_ASSERT_MSG(packet,
661  "CsmaNetDevice::TransmitReadyEvent(): IsEmpty false but no Packet on queue?");
662  m_currentPkt = packet;
665  TransmitStart();
666  }
667 }
668 
669 bool
671 {
672  NS_LOG_FUNCTION(this << &ch);
673 
674  m_channel = ch;
675 
676  m_deviceId = m_channel->Attach(this);
677 
678  NS_LOG_FUNCTION("Device ID is " << m_deviceId);
679 
680  //
681  // The channel provides us with the transmitter data rate.
682  //
683  m_bps = m_channel->GetDataRate();
684 
685  //
686  // We use the Ethernet interframe gap of 96 bit times.
687  //
689 
690  //
691  // This device is up whenever a channel is attached to it.
692  //
693  NotifyLinkUp();
694  return true;
695 }
696 
697 void
699 {
700  NS_LOG_FUNCTION(q);
701  m_queue = q;
702 }
703 
704 void
706 {
707  NS_LOG_FUNCTION(em);
708  m_receiveErrorModel = em;
709 }
710 
711 void
713 {
714  NS_LOG_FUNCTION(packet << senderDevice);
715  NS_LOG_LOGIC("UID is " << packet->GetUid());
716  NS_LOG_LOGIC("Device ID is " << m_deviceId);
717 
718  //
719  // We never forward up packets that we sent. Real devices don't do this since
720  // their receivers are disabled during send, so we don't.
721  //
722  if (senderDevice == this)
723  {
724  return;
725  }
726 
727  //
728  // Hit the trace hook. This trace will fire on all packets received from the
729  // channel except those originated by this device.
730  //
731  m_phyRxEndTrace(packet);
732 
733  //
734  // Only receive if the send side of net device is enabled
735  //
736  if (IsReceiveEnabled() == false)
737  {
738  m_phyRxDropTrace(packet);
739  return;
740  }
741 
742  if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt(packet))
743  {
744  NS_LOG_LOGIC("Dropping pkt due to error model ");
745  m_phyRxDropTrace(packet);
746  return;
747  }
748 
749  //
750  // Trace sinks will expect complete packets, not packets without some of the
751  // headers.
752  //
753  Ptr<Packet> originalPacket = packet->Copy();
754 
755  EthernetTrailer trailer;
756  packet->RemoveTrailer(trailer);
757  if (Node::ChecksumEnabled())
758  {
759  trailer.EnableFcs(true);
760  }
761 
762  bool crcGood = trailer.CheckFcs(packet);
763  if (!crcGood)
764  {
765  NS_LOG_INFO("CRC error on Packet " << packet);
766  m_phyRxDropTrace(packet);
767  return;
768  }
769 
770  EthernetHeader header(false);
771  packet->RemoveHeader(header);
772 
773  NS_LOG_LOGIC("Pkt source is " << header.GetSource());
774  NS_LOG_LOGIC("Pkt destination is " << header.GetDestination());
775 
776  uint16_t protocol;
777  //
778  // If the length/type is less than 1500, it corresponds to a length
779  // interpretation packet. In this case, it is an 802.3 packet and
780  // will also have an 802.2 LLC header. If greater than 1500, we
781  // find the protocol number (Ethernet type) directly.
782  //
783  if (header.GetLengthType() <= 1500)
784  {
785  NS_ASSERT(packet->GetSize() >= header.GetLengthType());
786  uint32_t padlen = packet->GetSize() - header.GetLengthType();
787  NS_ASSERT(padlen <= 46);
788  if (padlen > 0)
789  {
790  packet->RemoveAtEnd(padlen);
791  }
792 
793  LlcSnapHeader llc;
794  packet->RemoveHeader(llc);
795  protocol = llc.GetType();
796  }
797  else
798  {
799  protocol = header.GetLengthType();
800  }
801 
802  //
803  // Classify the packet based on its destination.
804  //
805  PacketType packetType;
806 
807  if (header.GetDestination().IsBroadcast())
808  {
809  packetType = PACKET_BROADCAST;
810  }
811  else if (header.GetDestination().IsGroup())
812  {
813  packetType = PACKET_MULTICAST;
814  }
815  else if (header.GetDestination() == m_address)
816  {
817  packetType = PACKET_HOST;
818  }
819  else
820  {
821  packetType = PACKET_OTHERHOST;
822  }
823 
824  //
825  // Check if this device is configure as an OpenFlow switch port.
826  //
828  {
829  // For all kinds of packet we receive, we hit the promiscuous sniffer
830  // hook. If the packet is addressed to this device (which is not supposed
831  // to happen in normal situations), we also hit the non-promiscuous
832  // sniffer hook, but in both cases we don't forward the packet up the
833  // stack.
834  m_promiscSnifferTrace(originalPacket);
835  if (packetType != PACKET_OTHERHOST)
836  {
837  m_snifferTrace(originalPacket);
838  }
839 
840  // We forward the original packet (which includes the EthernetHeader) to
841  // the OpenFlow receive callback for all kinds of packetType we receive
842  // (broadcast, multicast, host or other host).
844  originalPacket,
845  protocol,
846  header.GetSource(),
847  header.GetDestination(),
848  packetType);
849  return;
850  }
851 
852  //
853  // For all kinds of packetType we receive, we hit the promiscuous sniffer
854  // hook and pass a copy up to the promiscuous callback. Pass a copy to
855  // make sure that nobody messes with our packet.
856  //
857  m_promiscSnifferTrace(originalPacket);
859  {
860  m_macPromiscRxTrace(originalPacket);
861  m_promiscRxCallback(this,
862  packet,
863  protocol,
864  header.GetSource(),
865  header.GetDestination(),
866  packetType);
867  }
868 
869  //
870  // If this packet is not destined for some other host, it must be for us
871  // as either a broadcast, multicast or unicast. We need to hit the mac
872  // packet received trace hook and forward the packet up the stack.
873  //
874  if (packetType != PACKET_OTHERHOST)
875  {
876  m_snifferTrace(originalPacket);
877  m_macRxTrace(originalPacket);
878  m_rxCallback(this, packet, protocol, header.GetSource());
879  }
880 }
881 
884 {
886  return m_queue;
887 }
888 
889 void
891 {
893  m_linkUp = true;
895 }
896 
897 void
898 CsmaNetDevice::SetIfIndex(const uint32_t index)
899 {
900  NS_LOG_FUNCTION(index);
901  m_ifIndex = index;
902 }
903 
904 uint32_t
906 {
908  return m_ifIndex;
909 }
910 
913 {
915  return m_channel;
916 }
917 
918 void
920 {
923 }
924 
925 Address
927 {
929  return m_address;
930 }
931 
932 bool
934 {
936  return m_linkUp;
937 }
938 
939 void
941 {
942  NS_LOG_FUNCTION(&callback);
944 }
945 
946 bool
948 {
950  return true;
951 }
952 
953 Address
955 {
957  return Mac48Address("ff:ff:ff:ff:ff:ff");
958 }
959 
960 bool
962 {
964  return true;
965 }
966 
967 Address
969 {
970  NS_LOG_FUNCTION(multicastGroup);
971 
972  Mac48Address ad = Mac48Address::GetMulticast(multicastGroup);
973 
974  //
975  // Implicit conversion (operator Address ()) is defined for Mac48Address, so
976  // use it by just returning the EUI-48 address which is automagically converted
977  // to an Address.
978  //
979  NS_LOG_LOGIC("multicast address is " << ad);
980 
981  return ad;
982 }
983 
984 bool
986 {
988  return false;
989 }
990 
991 bool
993 {
995  return false;
996 }
997 
998 bool
999 CsmaNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
1000 {
1001  NS_LOG_FUNCTION(packet << dest << protocolNumber);
1002  return SendFrom(packet, m_address, dest, protocolNumber);
1003 }
1004 
1005 bool
1007  const Address& src,
1008  const Address& dest,
1009  uint16_t protocolNumber)
1010 {
1011  NS_LOG_FUNCTION(packet << src << dest << protocolNumber);
1012  NS_LOG_LOGIC("packet =" << packet);
1013  NS_LOG_LOGIC("UID is " << packet->GetUid() << ")");
1014  NS_LOG_LOGIC("Device ID is " << m_deviceId);
1015 
1016  NS_ASSERT(IsLinkUp());
1017 
1018  //
1019  // Only transmit if send side of net device is enabled
1020  //
1021  if (IsSendEnabled() == false)
1022  {
1023  m_macTxDropTrace(packet);
1024  return false;
1025  }
1026 
1027  Mac48Address destination = Mac48Address::ConvertFrom(dest);
1029  AddHeader(packet, source, destination, protocolNumber);
1030 
1031  m_macTxTrace(packet);
1032 
1033  //
1034  // Place the packet to be sent on the send queue. Note that the
1035  // queue may fire a drop trace, but we will too.
1036  //
1037  if (m_queue->Enqueue(packet) == false)
1038  {
1039  m_macTxDropTrace(packet);
1040  return false;
1041  }
1042 
1043  //
1044  // If the device is idle, we need to start a transmission. Otherwise,
1045  // the transmission will be started when the current packet finished
1046  // transmission (see TransmitCompleteEvent)
1047  //
1048  if (m_txMachineState == READY)
1049  {
1050  if (m_queue->IsEmpty() == false)
1051  {
1052  Ptr<Packet> packet = m_queue->Dequeue();
1053  NS_ASSERT_MSG(packet,
1054  "CsmaNetDevice::SendFrom(): IsEmpty false but no Packet on queue?");
1055  m_currentPkt = packet;
1058  TransmitStart();
1059  }
1060  }
1061  return true;
1062 }
1063 
1064 Ptr<Node>
1066 {
1068  return m_node;
1069 }
1070 
1071 void
1073 {
1074  NS_LOG_FUNCTION(node);
1075 
1076  m_node = node;
1077 }
1078 
1079 bool
1081 {
1083  return true;
1084 }
1085 
1086 void
1088 {
1089  NS_LOG_FUNCTION(&cb);
1090  m_openFlowRxCallback = cb;
1091 }
1092 
1093 void
1095 {
1096  NS_LOG_FUNCTION(&cb);
1097  m_rxCallback = cb;
1098 }
1099 
1100 Address
1102 {
1104 
1105  NS_LOG_LOGIC("MAC IPv6 multicast address is " << ad);
1106  return ad;
1107 }
1108 
1109 void
1111 {
1112  NS_LOG_FUNCTION(&cb);
1113  m_promiscRxCallback = cb;
1114 }
1115 
1116 bool
1118 {
1120  return true;
1121 }
1122 
1123 int64_t
1125 {
1126  return m_backoff.AssignStreams(stream);
1127 }
1128 
1129 } // namespace ns3
a polymophic address class
Definition: address.h:100
void ResetBackoffTime()
Indicates to the backoff object that the last packet was successfully transmitted and that the number...
Definition: backoff.cc:85
uint32_t m_maxRetries
Maximum number of transmission retries before the packet is dropped.
Definition: backoff.h:61
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: backoff.cc:103
uint32_t m_maxSlots
Maximum number of backoff slots (when multiplied by m_slotTime, determines maximum backoff time)
Definition: backoff.h:51
bool MaxRetriesReached() const
Definition: backoff.cc:91
void IncrNumRetries()
Increments the number of retries by 1.
Definition: backoff.cc:97
uint32_t m_minSlots
Minimum number of backoff slots (when multiplied by m_slotTime, determines minimum backoff time)
Definition: backoff.h:45
Time GetBackoffTime()
Definition: backoff.cc:58
uint32_t m_ceiling
Caps the exponential function when the number of retries reaches m_ceiling.
Definition: backoff.h:56
Time m_slotTime
Length of one slot.
Definition: backoff.h:67
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsNull() const
Check for null implementation.
Definition: callback.h:572
@ IDLE
Channel is IDLE, no packet is being transmitted.
Definition: csma-channel.h:100
@ TRANSMITTING
Channel is BUSY, a packet is being written by a net device.
Definition: csma-channel.h:101
A Device for a Csma Network Link.
void SetInterframeGap(Time t)
Set the interframe gap used to separate packets.
NetDevice::PromiscReceiveCallback m_openFlowRxCallback
The OpenFlow receive callback.
Ptr< Queue< Packet > > GetQueue() const
Get a copy of the attached Queue.
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
The trace source fired for packets successfully received by the device but dropped before being forwa...
Ptr< Node > GetNode() const override
Get the node to which this device is attached.
EncapsulationMode
Enumeration of the types of packets supported in the class.
@ ILLEGAL
Encapsulation mode not set.
@ DIX
DIX II / Ethernet II packet.
@ LLC
802.2 LLC/SNAP Packet
NetDevice::ReceiveCallback m_rxCallback
The callback used to notify higher layers that a packet has been received.
TracedCallback< Ptr< const Packet > > m_macTxBackoffTrace
The trace source fired when the mac layer is forced to begin the backoff process for a packet.
void SetReceiveEnable(bool enable)
Enable or disable the receive side of the network device.
void SetQueue(Ptr< Queue< Packet >> queue)
Attach a queue to the CsmaNetDevice.
Backoff m_backoff
Holds the backoff parameters and is used to calculate the next backoff time to use when the channel i...
DataRate m_bps
The data rate that the Net Device uses to simulate packet transmission timing.
void DoDispose() override
Perform any object release functionality required to break reference cycles in reference counted obje...
~CsmaNetDevice() override
Destroy a CsmaNetDevice.
bool SetMtu(const uint16_t mtu) override
void TransmitAbort()
Aborts the transmission of the current packet.
EncapsulationMode m_encapMode
The type of packet that should be created by the AddHeader function and that should be processed by t...
bool NeedsArp() const override
Does this device need to use the address resolution protocol?
void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb)
Set the callback used to notify the OpenFlow when a packet has been received by this device.
TracedCallback< Ptr< const Packet > > m_macRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
void TransmitStart()
Start Sending a Packet Down the Wire.
void SetIfIndex(const uint32_t index) override
@ BACKOFF
The transmitter is waiting for the channel to be free.
@ READY
The transmitter is ready to begin transmission of a packet.
@ BUSY
The transmitter is busy transmitting a packet.
@ GAP
The transmitter is in the interframe gap time.
Ptr< Queue< Packet > > m_queue
The Queue which this CsmaNetDevice uses as a packet source.
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
uint32_t m_mtu
The Maximum Transmission Unit.
bool SupportsSendFrom() const override
NetDevice::PromiscReceiveCallback m_promiscRxCallback
The callback used to notify higher layers that a packet has been received in promiscuous mode.
CsmaNetDevice()
Construct a CsmaNetDevice.
void SetPromiscReceiveCallback(PromiscReceiveCallback cb) override
Address GetBroadcast() const override
static TypeId GetTypeId()
Get the type ID.
bool IsPointToPoint() const override
Is this a point to point link?
Ptr< CsmaChannel > m_channel
The CsmaChannel to which this CsmaNetDevice has been attached.
bool Attach(Ptr< CsmaChannel > ch)
Attach the device to a channel.
bool IsBridge() const override
Is this a bridge?
void TransmitCompleteEvent()
Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber) override
Start sending a packet down the channel, with MAC spoofing.
void Receive(Ptr< Packet > p, Ptr< CsmaNetDevice > sender)
Receive a packet from a connected CsmaChannel.
bool IsMulticast() const override
TracedCallback m_linkChangeCallbacks
List of callbacks to fire if the link changes state (up or down).
TracedCallback< Ptr< const Packet > > m_phyTxBeginTrace
The trace source fired when a packet begins the transmission process on the medium.
CsmaNetDevice::EncapsulationMode GetEncapsulationMode()
Get the encapsulation mode of this device.
void AddHeader(Ptr< Packet > p, Mac48Address source, Mac48Address dest, uint16_t protocolNumber)
Adds the necessary headers and trailers to a packet of data in order to respect the packet type.
uint16_t GetMtu() const override
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< Channel > GetChannel() const override
void NotifyLinkUp()
Notify any interested parties that the link has come up.
void SetBackoffParams(Time slotTime, uint32_t minSlots, uint32_t maxSlots, uint32_t maxRetries, uint32_t ceiling)
Set the backoff parameters used to determine the wait to retry transmitting a packet when the channel...
Ptr< Packet > m_currentPkt
Next packet that will be transmitted (if transmitter is not currently transmitting) or packet that is...
TracedCallback< Ptr< const Packet > > m_snifferTrace
A trace source that emulates a non-promiscuous protocol sniffer connected to the device.
TracedCallback< Ptr< const Packet > > m_phyTxEndTrace
The trace source fired when a packet ends the transmission process on the medium.
uint32_t m_deviceId
Device ID returned by the attached functions.
bool m_receiveEnable
Enable net device to receive packets.
TracedCallback< Ptr< const Packet > > m_phyRxDropTrace
The trace source fired when the phy layer drops a packet it has received.
Address GetMulticast(Ipv4Address multicastGroup) const override
Make and return a MAC multicast address using the provided multicast group.
Ptr< Node > m_node
The Node to which this device is attached.
void SetReceiveErrorModel(Ptr< ErrorModel > em)
Attach a receive ErrorModel to the CsmaNetDevice.
void SetSendEnable(bool enable)
Enable or disable the send side of the network device.
bool IsLinkUp() const override
void TransmitReadyEvent()
Cause the Transmitter to Become Ready to Send Another Packet.
TracedCallback< Ptr< const Packet > > m_promiscSnifferTrace
A trace source that emulates a promiscuous mode protocol sniffer connected to the device.
uint32_t GetIfIndex() const override
bool IsBroadcast() const override
static const uint16_t DEFAULT_MTU
Default Maximum Transmission Unit (MTU) for the CsmaNetDevice.
void SetEncapsulationMode(CsmaNetDevice::EncapsulationMode mode)
Set the encapsulation mode of this device.
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
bool m_sendEnable
Enable net device to send packets.
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
The trace source fired when packets coming into the "top" of the device at the L3/L2 transition are d...
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Start sending a packet down the channel.
bool IsSendEnabled() const
Is the send side of the network device enabled?
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition,...
void SetReceiveCallback(NetDevice::ReceiveCallback cb) override
Set the callback to be used to notify higher layers when a packet has been received.
TracedCallback< Ptr< const Packet > > m_phyTxDropTrace
The trace source fired when the phy layer drops a packet as it tries to transmit it.
Address GetAddress() const override
void AddLinkChangeCallback(Callback< void > callback) override
void SetNode(Ptr< Node > node) override
Set the node to which this device is being attached.
void SetAddress(Address address) override
Set the address of this interface.
Mac48Address m_address
The MAC address which has been assigned to this device.
Time m_tInterframeGap
The interframe gap that the Net Device uses insert time between packet transmission.
Ptr< ErrorModel > m_receiveErrorModel
Error model for receive packet events.
TxMachineState m_txMachineState
The state of the Net Device transmit state machine.
uint32_t m_ifIndex
The interface index (really net evice index) that has been assigned to this network device.
bool IsReceiveEnabled() const
Is the receive side of the network device enabled?
bool m_linkUp
Flag indicating whether or not the link is up.
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
The trace source fired when a packet ends the reception process from the medium.
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:291
Hold variables of type enum.
Definition: enum.h:56
Packet header for Ethernet.
uint16_t GetLengthType() const
void SetDestination(Mac48Address destination)
Mac48Address GetDestination() const
void SetLengthType(uint16_t size)
void SetSource(Mac48Address source)
Mac48Address GetSource() const
Packet trailer for Ethernet.
bool CheckFcs(Ptr< const Packet > p) const
Calculate an FCS on the provided packet and check this value against the FCS found when the trailer w...
void EnableFcs(bool enable)
Enable or disable FCS checking and calculations.
void CalcFcs(Ptr< const Packet > p)
Updates the Fcs Field to the correct FCS.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
Describes an IPv6 address.
Definition: ipv6-address.h:50
Header for the LLC/SNAP encapsulation.
uint16_t GetType()
Return the Ethertype.
void SetType(uint16_t type)
Set the Ethertype.
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address GetMulticast(Ipv4Address address)
bool IsGroup() const
static Mac48Address ConvertFrom(const Address &address)
bool IsBroadcast() const
AttributeValue implementation for Mac48Address.
Network layer to device interface.
Definition: net-device.h:98
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:300
@ PACKET_HOST
Packet addressed to us.
Definition: net-device.h:301
@ PACKET_OTHERHOST
Packet addressed to someone else.
Definition: net-device.h:307
@ PACKET_BROADCAST
Packet addressed to all.
Definition: net-device.h:303
@ PACKET_MULTICAST
Packet addressed to multicast group.
Definition: net-device.h:305
static bool ChecksumEnabled()
Definition: node.cc:290
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:336
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:376
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:324
Hold objects of type Ptr<T>.
Definition: pointer.h:37
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
@ S
second
Definition: nstime.h:116
void ConnectWithoutContext(const CallbackBase &callback)
Append a Callback to the chain (without a context).
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: enum.h:205
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: pointer.h:231
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:163