A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
csma-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 Emmanuelle Laprise
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  * Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/queue.h"
23 #include "ns3/simulator.h"
24 #include "ns3/ethernet-header.h"
25 #include "ns3/ethernet-trailer.h"
26 #include "ns3/llc-snap-header.h"
27 #include "ns3/error-model.h"
28 #include "ns3/enum.h"
29 #include "ns3/boolean.h"
30 #include "ns3/uinteger.h"
31 #include "ns3/pointer.h"
32 #include "ns3/trace-source-accessor.h"
33 #include "csma-net-device.h"
34 #include "csma-channel.h"
35 
36 NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
37 
38 namespace ns3 {
39 
40 NS_OBJECT_ENSURE_REGISTERED (CsmaNetDevice);
41 
42 TypeId
44 {
45  static TypeId tid = TypeId ("ns3::CsmaNetDevice")
46  .SetParent<NetDevice> ()
47  .AddConstructor<CsmaNetDevice> ()
48  .AddAttribute ("Address",
49  "The MAC address of this device.",
50  Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
51  MakeMac48AddressAccessor (&CsmaNetDevice::m_address),
52  MakeMac48AddressChecker ())
53  .AddAttribute ("Mtu", "The MAC-level Maximum Transmission Unit",
55  MakeUintegerAccessor (&CsmaNetDevice::SetMtu,
57  MakeUintegerChecker<uint16_t> ())
58  .AddAttribute ("EncapsulationMode",
59  "The link-layer encapsulation type to use.",
60  EnumValue (DIX),
62  MakeEnumChecker (DIX, "Dix",
63  LLC, "Llc"))
64  .AddAttribute ("SendEnable",
65  "Enable or disable the transmitter section of the device.",
66  BooleanValue (true),
67  MakeBooleanAccessor (&CsmaNetDevice::m_sendEnable),
68  MakeBooleanChecker ())
69  .AddAttribute ("ReceiveEnable",
70  "Enable or disable the receiver section of the device.",
71  BooleanValue (true),
72  MakeBooleanAccessor (&CsmaNetDevice::m_receiveEnable),
73  MakeBooleanChecker ())
74  .AddAttribute ("ReceiveErrorModel",
75  "The receiver error model used to simulate packet loss",
76  PointerValue (),
77  MakePointerAccessor (&CsmaNetDevice::m_receiveErrorModel),
78  MakePointerChecker<ErrorModel> ())
79 
80  //
81  // Transmit queueing discipline for the device which includes its own set
82  // of trace hooks.
83  //
84  .AddAttribute ("TxQueue",
85  "A queue to use as the transmit queue in the device.",
86  PointerValue (),
87  MakePointerAccessor (&CsmaNetDevice::m_queue),
88  MakePointerChecker<Queue> ())
89 
90  //
91  // Trace sources at the "top" of the net device, where packets transition
92  // to/from higher layers.
93  //
94  .AddTraceSource ("MacTx",
95  "Trace source indicating a packet has arrived for transmission by this device",
97  .AddTraceSource ("MacTxDrop",
98  "Trace source indicating a packet has been dropped by the device before transmission",
100  .AddTraceSource ("MacPromiscRx",
101  "A packet has been received by this device, has been passed up from the physical layer "
102  "and is being forwarded up the local protocol stack. This is a promiscuous trace,",
104  .AddTraceSource ("MacRx",
105  "A packet has been received by this device, has been passed up from the physical layer "
106  "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,",
108 #if 0
109  // Not currently implemented in this device
110  .AddTraceSource ("MacRxDrop",
111  "Trace source indicating a packet was received, but dropped before being forwarded up the stack",
113 #endif
114  .AddTraceSource ("MacTxBackoff",
115  "Trace source indicating a packet has been delayed by the CSMA backoff process",
117  //
118  // Trace souces at the "bottom" of the net device, where packets transition
119  // to/from the channel.
120  //
121  .AddTraceSource ("PhyTxBegin",
122  "Trace source indicating a packet has begun transmitting over the channel",
124  .AddTraceSource ("PhyTxEnd",
125  "Trace source indicating a packet has been completely transmitted over the channel",
127  .AddTraceSource ("PhyTxDrop",
128  "Trace source indicating a packet has been dropped by the device during transmission",
130 #if 0
131  // Not currently implemented in this device
132  .AddTraceSource ("PhyRxBegin",
133  "Trace source indicating a packet has begun being received by the device",
135 #endif
136  .AddTraceSource ("PhyRxEnd",
137  "Trace source indicating a packet has been completely received by the device",
139  .AddTraceSource ("PhyRxDrop",
140  "Trace source indicating a packet has been dropped by the device during reception",
142  //
143  // Trace sources designed to simulate a packet sniffer facility (tcpdump).
144  //
145  .AddTraceSource ("Sniffer",
146  "Trace source simulating a non-promiscuous packet sniffer attached to the device",
148  .AddTraceSource ("PromiscSniffer",
149  "Trace source simulating a promiscuous packet sniffer attached to the device",
151  ;
152  return tid;
153 }
154 
156  : m_linkUp (false)
157 {
158  NS_LOG_FUNCTION (this);
161  m_channel = 0;
162 
163  //
164  // We would like to let the attribute system take care of initializing the
165  // packet encapsulation stuff, but we also don't want to get caught up in
166  // initialization order changes. So we'll get the three problem variables
167  // into a consistent state here before the attribute calls, and then depend
168  // on the semantics of the setters to preserve a consistent state. This
169  // really doesn't have to be the same set of values as the initial values
170  // set by the attributes, but it does have to be a consistent set. That is,
171  // you can just change the default encapsulation mode above without having
172  // to change it here.
173  //
174  m_encapMode = DIX;
175 }
176 
178 {
180  m_queue = 0;
181 }
182 
183 void
185 {
187  m_channel = 0;
188  m_node = 0;
190 }
191 
192 void
194 {
195  NS_LOG_FUNCTION (mode);
196 
197  m_encapMode = mode;
198 
199  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
200  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
201 }
202 
205 {
207  return m_encapMode;
208 }
209 
210 bool
211 CsmaNetDevice::SetMtu (uint16_t mtu)
212 {
213  NS_LOG_FUNCTION (this << mtu);
214  m_mtu = mtu;
215 
216  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
217  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
218 
219  return true;
220 }
221 
222 uint16_t
224 {
226  return m_mtu;
227 }
228 
229 
230 void
232 {
233  NS_LOG_FUNCTION (sendEnable);
234  m_sendEnable = sendEnable;
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION (receiveEnable);
241  m_receiveEnable = receiveEnable;
242 }
243 
244 bool
246 {
248  return m_sendEnable;
249 }
250 
251 bool
253 {
255  return m_receiveEnable;
256 }
257 
258 void
260 {
261  NS_LOG_FUNCTION (t);
262  m_tInterframeGap = t;
263 }
264 
265 void
266 CsmaNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots, uint32_t ceiling, uint32_t maxRetries)
267 {
268  NS_LOG_FUNCTION (slotTime << minSlots << maxSlots << ceiling << maxRetries);
269  m_backoff.m_slotTime = slotTime;
270  m_backoff.m_minSlots = minSlots;
271  m_backoff.m_maxSlots = maxSlots;
272  m_backoff.m_ceiling = ceiling;
273  m_backoff.m_maxRetries = maxRetries;
274 }
275 
276 void
277 CsmaNetDevice::AddHeader (Ptr<Packet> p, Mac48Address source, Mac48Address dest, uint16_t protocolNumber)
278 {
279  NS_LOG_FUNCTION (p << source << dest << protocolNumber);
280 
281  EthernetHeader header (false);
282  header.SetSource (source);
283  header.SetDestination (dest);
284 
285  EthernetTrailer trailer;
286 
287  NS_LOG_LOGIC ("p->GetSize () = " << p->GetSize ());
288  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
289  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
290 
291  uint16_t lengthType = 0;
292  switch (m_encapMode)
293  {
294  case DIX:
295  NS_LOG_LOGIC ("Encapsulating packet as DIX (type interpretation)");
296  //
297  // This corresponds to the type interpretation of the lengthType field as
298  // in the old Ethernet Blue Book.
299  //
300  lengthType = protocolNumber;
301 
302  //
303  // All Ethernet frames must carry a minimum payload of 46 bytes. We need
304  // to pad out if we don't have enough bytes. These must be real bytes
305  // since they will be written to pcap files and compared in regression
306  // trace files.
307  //
308  if (p->GetSize () < 46)
309  {
310  uint8_t buffer[46];
311  memset (buffer, 0, 46);
312  Ptr<Packet> padd = Create<Packet> (buffer, 46 - p->GetSize ());
313  p->AddAtEnd (padd);
314  }
315  break;
316  case LLC:
317  {
318  NS_LOG_LOGIC ("Encapsulating packet as LLC (length interpretation)");
319 
320  LlcSnapHeader llc;
321  llc.SetType (protocolNumber);
322  p->AddHeader (llc);
323 
324  //
325  // This corresponds to the length interpretation of the lengthType
326  // field but with an LLC/SNAP header added to the payload as in
327  // IEEE 802.2
328  //
329  lengthType = p->GetSize ();
330 
331  //
332  // All Ethernet frames must carry a minimum payload of 46 bytes. The
333  // LLC SNAP header counts as part of this payload. We need to padd out
334  // if we don't have enough bytes. These must be real bytes since they
335  // will be written to pcap files and compared in regression trace files.
336  //
337  if (p->GetSize () < 46)
338  {
339  uint8_t buffer[46];
340  memset (buffer, 0, 46);
341  Ptr<Packet> padd = Create<Packet> (buffer, 46 - p->GetSize ());
342  p->AddAtEnd (padd);
343  }
344 
345  NS_ASSERT_MSG (p->GetSize () <= GetMtu (),
346  "CsmaNetDevice::AddHeader(): 802.3 Length/Type field with LLC/SNAP: "
347  "length interpretation must not exceed device frame size minus overhead");
348  }
349  break;
350  case ILLEGAL:
351  default:
352  NS_FATAL_ERROR ("CsmaNetDevice::AddHeader(): Unknown packet encapsulation mode");
353  break;
354  }
355 
356  NS_LOG_LOGIC ("header.SetLengthType (" << lengthType << ")");
357  header.SetLengthType (lengthType);
358  p->AddHeader (header);
359 
360  if (Node::ChecksumEnabled ())
361  {
362  trailer.EnableFcs (true);
363  }
364  trailer.CalcFcs (p);
365  p->AddTrailer (trailer);
366 }
367 
368 #if 0
369 bool
370 CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
371 {
372  NS_LOG_FUNCTION (p << param);
373 
374  EthernetTrailer trailer;
375  p->RemoveTrailer (trailer);
376 
377  EthernetHeader header (false);
378  p->RemoveHeader (header);
379 
380  if ((header.GetDestination () != GetBroadcast ()) &&
381  (header.GetDestination () != GetAddress ()))
382  {
383  return false;
384  }
385 
386  switch (m_encapMode)
387  {
388  case DIX:
389  param = header.GetLengthType ();
390  break;
391  case LLC:
392  {
393  LlcSnapHeader llc;
394  p->RemoveHeader (llc);
395  param = llc.GetType ();
396  }
397  break;
398  case ILLEGAL:
399  default:
400  NS_FATAL_ERROR ("CsmaNetDevice::ProcessHeader(): Unknown packet encapsulation mode");
401  break;
402  }
403  return true;
404 }
405 #endif
406 
407 void
409 {
411 
412  //
413  // This function is called to start the process of transmitting a packet. We
414  // expect that the packet to transmit will be found in m_currentPkt.
415  //
416  NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitStart(): m_currentPkt not set");
417 
418  NS_LOG_LOGIC ("m_currentPkt = " << m_currentPkt);
419  NS_LOG_LOGIC ("UID = " << m_currentPkt->GetUid ());
420 
421  //
422  // Only transmit if the send side of net device is enabled
423  //
424  if (IsSendEnabled () == false)
425  {
427  m_currentPkt = 0;
428  return;
429  }
430 
431  //
432  // Somebody has called here telling us to start transmitting a packet. They
433  // can only do this if the state machine is in the READY or BACKOFF state.
434  // Specifically, if we are ready to start transmitting, we cannot already
435  // be transmitting (i.e., BUSY)
436  //
438  "Must be READY to transmit. Tx state is: " << m_txMachineState);
439 
440  //
441  // Now we have to sense the state of the medium and either start transmitting
442  // if it is idle, or backoff our transmission if someone else is on the wire.
443  //
444  if (m_channel->GetState () != IDLE)
445  {
446  //
447  // The channel is busy -- backoff and rechedule TransmitStart() unless
448  // we have exhausted all of our retries.
449  //
451 
453  {
454  //
455  // Too many retries, abort transmission of packet
456  //
457  TransmitAbort ();
458  }
459  else
460  {
462 
464  Time backoffTime = m_backoff.GetBackoffTime ();
465 
466  NS_LOG_LOGIC ("Channel busy, backing off for " << backoffTime.GetSeconds () << " sec");
467 
469  }
470  }
471  else
472  {
473  //
474  // The channel is free, transmit the packet
475  //
477  {
478  NS_LOG_WARN ("Channel TransmitStart returns an error");
480  m_currentPkt = 0;
482  }
483  else
484  {
485  //
486  // Transmission succeeded, reset the backoff time parameters and
487  // schedule a transmit complete event.
488  //
492 
494  NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << tEvent.GetSeconds () << "sec");
496  }
497  }
498 }
499 
500 void
502 {
504 
505  //
506  // When we started the process of transmitting the current packet, it was
507  // placed in m_currentPkt. So we had better find one there.
508  //
509  NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitAbort(): m_currentPkt zero");
510  NS_LOG_LOGIC ("m_currentPkt=" << m_currentPkt);
511  NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
512 
514  m_currentPkt = 0;
515 
516  NS_ASSERT_MSG (m_txMachineState == BACKOFF, "Must be in BACKOFF state to abort. Tx state is: " << m_txMachineState);
517 
518  //
519  // We're done with that one, so reset the backoff algorithm and ready the
520  // transmit state machine.
521  //
524 
525  //
526  // If there is another packet on the input queue, we need to start trying to
527  // get that out. If the queue is empty we just wait until someone puts one
528  // in.
529  //
530  if (m_queue->IsEmpty ())
531  {
532  return;
533  }
534  else
535  {
537  NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitAbort(): IsEmpty false but no Packet on queue?");
540  TransmitStart ();
541  }
542 }
543 
544 void
546 {
548 
549  //
550  // This function is called to finish the process of transmitting a packet.
551  // We need to tell the channel that we've stopped wiggling the wire and
552  // schedule an event that will be executed when it's time to re-enable
553  // the transmitter after the interframe gap.
554  //
555  NS_ASSERT_MSG (m_txMachineState == BUSY, "CsmaNetDevice::transmitCompleteEvent(): Must be BUSY if transmitting");
558 
559  //
560  // When we started transmitting the current packet, it was placed in
561  // m_currentPkt. So we had better find one there.
562  //
563  NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitCompleteEvent(): m_currentPkt zero");
564  NS_LOG_LOGIC ("m_currentPkt=" << m_currentPkt);
565  NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
566 
567  m_channel->TransmitEnd ();
569  m_currentPkt = 0;
570 
571  NS_LOG_LOGIC ("Schedule TransmitReadyEvent in " << m_tInterframeGap.GetSeconds () << "sec");
572 
574 }
575 
576 void
578 {
580 
581  //
582  // This function is called to enable the transmitter after the interframe
583  // gap has passed. If there are pending transmissions, we use this opportunity
584  // to start the next transmit.
585  //
586  NS_ASSERT_MSG (m_txMachineState == GAP, "CsmaNetDevice::TransmitReadyEvent(): Must be in interframe gap");
588 
589  //
590  // We expect that the packet we had been transmitting was cleared when the
591  // TransmitCompleteEvent() was executed.
592  //
593  NS_ASSERT_MSG (m_currentPkt == 0, "CsmaNetDevice::TransmitReadyEvent(): m_currentPkt nonzero");
594 
595  //
596  // Get the next packet from the queue for transmitting
597  //
598  if (m_queue->IsEmpty ())
599  {
600  return;
601  }
602  else
603  {
605  NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitReadyEvent(): IsEmpty false but no Packet on queue?");
608  TransmitStart ();
609  }
610 }
611 
612 bool
614 {
615  NS_LOG_FUNCTION (this << &ch);
616 
617  m_channel = ch;
618 
619  m_deviceId = m_channel->Attach (this);
620 
621  //
622  // The channel provides us with the transmitter data rate.
623  //
625 
626  //
627  // We use the Ethernet interframe gap of 96 bit times.
628  //
630 
631  //
632  // This device is up whenever a channel is attached to it.
633  //
634  NotifyLinkUp ();
635  return true;
636 }
637 
638 void
640 {
641  NS_LOG_FUNCTION (q);
642  m_queue = q;
643 }
644 
645 void
647 {
648  NS_LOG_FUNCTION (em);
649  m_receiveErrorModel = em;
650 }
651 
652 void
654 {
655  NS_LOG_FUNCTION (packet << senderDevice);
656  NS_LOG_LOGIC ("UID is " << packet->GetUid ());
657 
658  //
659  // We never forward up packets that we sent. Real devices don't do this since
660  // their receivers are disabled during send, so we don't.
661  //
662  if (senderDevice == this)
663  {
664  return;
665  }
666 
667  //
668  // Hit the trace hook. This trace will fire on all packets received from the
669  // channel except those originated by this device.
670  //
671  m_phyRxEndTrace (packet);
672 
673  //
674  // Only receive if the send side of net device is enabled
675  //
676  if (IsReceiveEnabled () == false)
677  {
678  m_phyRxDropTrace (packet);
679  return;
680  }
681 
683  {
684  NS_LOG_LOGIC ("Dropping pkt due to error model ");
685  m_phyRxDropTrace (packet);
686  return;
687  }
688 
689  //
690  // Trace sinks will expect complete packets, not packets without some of the
691  // headers.
692  //
693  Ptr<Packet> originalPacket = packet->Copy ();
694 
695  EthernetTrailer trailer;
696  packet->RemoveTrailer (trailer);
697  if (Node::ChecksumEnabled ())
698  {
699  trailer.EnableFcs (true);
700  }
701 
702  trailer.CheckFcs (packet);
703  bool crcGood = trailer.CheckFcs (packet);
704  if (!crcGood)
705  {
706  NS_LOG_INFO ("CRC error on Packet " << packet);
707  m_phyRxDropTrace (packet);
708  return;
709  }
710 
711  EthernetHeader header (false);
712  packet->RemoveHeader (header);
713 
714  NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
715  NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
716 
717  uint16_t protocol;
718  //
719  // If the length/type is less than 1500, it corresponds to a length
720  // interpretation packet. In this case, it is an 802.3 packet and
721  // will also have an 802.2 LLC header. If greater than 1500, we
722  // find the protocol number (Ethernet type) directly.
723  //
724  if (header.GetLengthType () <= 1500)
725  {
726  NS_ASSERT (packet->GetSize () >= header.GetLengthType ());
727  uint32_t padlen = packet->GetSize () - header.GetLengthType ();
728  NS_ASSERT (padlen <= 46);
729  if (padlen > 0)
730  {
731  packet->RemoveAtEnd (padlen);
732  }
733 
734  LlcSnapHeader llc;
735  packet->RemoveHeader (llc);
736  protocol = llc.GetType ();
737  }
738  else
739  {
740  protocol = header.GetLengthType ();
741  }
742 
743  //
744  // Classify the packet based on its destination.
745  //
746  PacketType packetType;
747 
748  if (header.GetDestination ().IsBroadcast ())
749  {
750  packetType = PACKET_BROADCAST;
751  }
752  else if (header.GetDestination ().IsGroup ())
753  {
754  packetType = PACKET_MULTICAST;
755  }
756  else if (header.GetDestination () == m_address)
757  {
758  packetType = PACKET_HOST;
759  }
760  else
761  {
762  packetType = PACKET_OTHERHOST;
763  }
764 
765  //
766  // For all kinds of packetType we receive, we hit the promiscuous sniffer
767  // hook and pass a copy up to the promiscuous callback. Pass a copy to
768  // make sure that nobody messes with our packet.
769  //
770  m_promiscSnifferTrace (originalPacket);
771  if (!m_promiscRxCallback.IsNull ())
772  {
773  m_macPromiscRxTrace (originalPacket);
774  m_promiscRxCallback (this, packet, protocol, header.GetSource (), header.GetDestination (), packetType);
775  }
776 
777  //
778  // If this packet is not destined for some other host, it must be for us
779  // as either a broadcast, multicast or unicast. We need to hit the mac
780  // packet received trace hook and forward the packet up the stack.
781  //
782  if (packetType != PACKET_OTHERHOST)
783  {
784  m_snifferTrace (originalPacket);
785  m_macRxTrace (originalPacket);
786  m_rxCallback (this, packet, protocol, header.GetSource ());
787  }
788 }
789 
792 {
794  return m_queue;
795 }
796 
797 void
799 {
801  m_linkUp = true;
803 }
804 
805 void
806 CsmaNetDevice::SetIfIndex (const uint32_t index)
807 {
808  NS_LOG_FUNCTION (index);
809  m_ifIndex = index;
810 }
811 
812 uint32_t
814 {
816  return m_ifIndex;
817 }
818 
821 {
823  return m_channel;
824 }
825 
826 void
828 {
831 }
832 
833 Address
835 {
837  return m_address;
838 }
839 
840 bool
842 {
844  return m_linkUp;
845 }
846 
847 void
849 {
850  NS_LOG_FUNCTION (&callback);
852 }
853 
854 bool
856 {
858  return true;
859 }
860 
861 Address
863 {
865  return Mac48Address ("ff:ff:ff:ff:ff:ff");
866 }
867 
868 bool
870 {
872  return true;
873 }
874 
875 Address
877 {
878  NS_LOG_FUNCTION (multicastGroup);
879 
880  Mac48Address ad = Mac48Address::GetMulticast (multicastGroup);
881 
882  //
883  // Implicit conversion (operator Address ()) is defined for Mac48Address, so
884  // use it by just returning the EUI-48 address which is automagically converted
885  // to an Address.
886  //
887  NS_LOG_LOGIC ("multicast address is " << ad);
888 
889  return ad;
890 }
891 
892 bool
894 {
896  return false;
897 }
898 
899 bool
901 {
903  return false;
904 }
905 
906 bool
907 CsmaNetDevice::Send (Ptr<Packet> packet,const Address& dest, uint16_t protocolNumber)
908 {
909  NS_LOG_FUNCTION (packet << dest << protocolNumber);
910  return SendFrom (packet, m_address, dest, protocolNumber);
911 }
912 
913 bool
914 CsmaNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
915 {
916  NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
917  NS_LOG_LOGIC ("packet =" << packet);
918  NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
919 
920  NS_ASSERT (IsLinkUp ());
921 
922  //
923  // Only transmit if send side of net device is enabled
924  //
925  if (IsSendEnabled () == false)
926  {
927  m_macTxDropTrace (packet);
928  return false;
929  }
930 
931  Mac48Address destination = Mac48Address::ConvertFrom (dest);
933  AddHeader (packet, source, destination, protocolNumber);
934 
935  m_macTxTrace (packet);
936 
937  //
938  // Place the packet to be sent on the send queue. Note that the
939  // queue may fire a drop trace, but we will too.
940  //
941  if (m_queue->Enqueue (packet) == false)
942  {
943  m_macTxDropTrace (packet);
944  return false;
945  }
946 
947  //
948  // If the device is idle, we need to start a transmission. Otherwise,
949  // the transmission will be started when the current packet finished
950  // transmission (see TransmitCompleteEvent)
951  //
952  if (m_txMachineState == READY)
953  {
954  if (m_queue->IsEmpty () == false)
955  {
957  NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::SendFrom(): IsEmpty false but no Packet on queue?");
960  TransmitStart ();
961  }
962  }
963  return true;
964 }
965 
966 Ptr<Node>
968 {
970  return m_node;
971 }
972 
973 void
975 {
976  NS_LOG_FUNCTION (node);
977 
978  m_node = node;
979 }
980 
981 bool
983 {
985  return true;
986 }
987 
988 void
990 {
991  NS_LOG_FUNCTION (&cb);
992  m_rxCallback = cb;
993 }
994 
996 {
998 
999  NS_LOG_LOGIC ("MAC IPv6 multicast address is " << ad);
1000  return ad;
1001 }
1002 
1003 void
1005 {
1006  NS_LOG_FUNCTION (&cb);
1007  m_promiscRxCallback = cb;
1008 }
1009 
1010 bool
1012 {
1014  return true;
1015 }
1016 
1017 int64_t
1019 {
1020  return m_backoff.AssignStreams (stream);
1021 }
1022 
1023 } // namespace ns3