1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2007 Emmanuelle Laprise
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;
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.
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
18 * Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
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"
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"
36 NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
40 NS_OBJECT_ENSURE_REGISTERED (CsmaNetDevice);
43 CsmaNetDevice::GetTypeId (void)
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 ("FrameSize",
54 "The maximum size of a packet sent over this device.",
55 UintegerValue (DEFAULT_FRAME_SIZE),
56 MakeUintegerAccessor (&CsmaNetDevice::SetFrameSize,
57 &CsmaNetDevice::GetFrameSize),
58 MakeUintegerChecker<uint16_t> ())
59 .AddAttribute ("EncapsulationMode",
60 "The link-layer encapsulation type to use.",
62 MakeEnumAccessor (&CsmaNetDevice::SetEncapsulationMode),
63 MakeEnumChecker (DIX, "Dix",
65 .AddAttribute ("SendEnable",
66 "Enable or disable the transmitter section of the device.",
68 MakeBooleanAccessor (&CsmaNetDevice::m_sendEnable),
69 MakeBooleanChecker ())
70 .AddAttribute ("ReceiveEnable",
71 "Enable or disable the receiver section of the device.",
73 MakeBooleanAccessor (&CsmaNetDevice::m_receiveEnable),
74 MakeBooleanChecker ())
75 .AddAttribute ("RxErrorModel",
76 "The receiver error model used to simulate packet loss",
78 MakePointerAccessor (&CsmaNetDevice::m_receiveErrorModel),
79 MakePointerChecker<ErrorModel> ())
80 .AddAttribute ("TxQueue",
81 "A queue to use as the transmit queue in the device.",
83 MakePointerAccessor (&CsmaNetDevice::m_queue),
84 MakePointerChecker<Queue> ())
85 .AddTraceSource ("Rx",
86 "The trace source to fire on reception of a MAC packet.",
87 MakeTraceSourceAccessor (&CsmaNetDevice::m_rxTrace))
88 .AddTraceSource ("Drop",
89 "Trace source to fire on when a MAC packet is dropped.",
90 MakeTraceSourceAccessor (&CsmaNetDevice::m_dropTrace))
95 CsmaNetDevice::CsmaNetDevice ()
99 NS_LOG_FUNCTION (this);
100 m_txMachineState = READY;
101 m_tInterframeGap = Seconds (0);
105 // We would like to let the attribute system take care of initializing the packet encapsulation stuff, but we also don't want to
106 // get caught up in initialization order changes. So we'll get the three problem variables into a consistent state here before the
107 // attribute calls, and then depend on the semantics of the setters to preserve a consistent state. This really doesn't have to be
108 // the same set of values as the initial values set by the attributes, but it does have to be a consistent set. That is, you can
109 // just change the ddfault encapsulation mode above without having to change it here. We keep it the same for GP.
112 m_frameSize = DEFAULT_FRAME_SIZE;
113 m_mtu = MtuFromFrameSize (m_frameSize);
116 CsmaNetDevice::~CsmaNetDevice()
118 NS_LOG_FUNCTION_NOARGS ();
123 CsmaNetDevice::DoDispose ()
125 NS_LOG_FUNCTION_NOARGS ();
128 NetDevice::DoDispose ();
132 CsmaNetDevice::MtuFromFrameSize (uint32_t frameSize)
134 NS_LOG_FUNCTION (frameSize);
136 NS_ASSERT_MSG (frameSize <= std::numeric_limits<uint16_t>::max (),
137 "CsmaNetDevice::MtuFromFrameSize(): Frame size should be derived from 16-bit quantity: " << frameSize);
144 newSize = frameSize - ETHERNET_OVERHEAD;
150 NS_ASSERT_MSG ((uint32_t)(frameSize - ETHERNET_OVERHEAD) >= llc.GetSerializedSize (),
151 "CsmaNetDevice::MtuFromFrameSize(): Given frame size too small to support LLC mode");
152 newSize = frameSize - ETHERNET_OVERHEAD - llc.GetSerializedSize ();
157 NS_FATAL_ERROR ("CsmaNetDevice::MtuFromFrameSize(): Unknown packet encapsulation mode");
165 CsmaNetDevice::FrameSizeFromMtu (uint32_t mtu)
167 NS_LOG_FUNCTION (mtu);
174 newSize = mtu + ETHERNET_OVERHEAD;
179 newSize = mtu + ETHERNET_OVERHEAD + llc.GetSerializedSize ();
184 NS_FATAL_ERROR ("CsmaNetDevice::FrameSizeFromMtu(): Unknown packet encapsulation mode");
192 CsmaNetDevice::SetEncapsulationMode (enum EncapsulationMode mode)
194 NS_LOG_FUNCTION (mode);
197 m_mtu = MtuFromFrameSize (m_frameSize);
199 NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
200 NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
201 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
204 CsmaNetDevice::EncapsulationMode
205 CsmaNetDevice::GetEncapsulationMode (void)
207 NS_LOG_FUNCTION_NOARGS ();
212 CsmaNetDevice::SetMtu (uint16_t mtu)
214 NS_LOG_FUNCTION (mtu);
216 uint32_t newFrameSize = FrameSizeFromMtu (mtu);
218 if (newFrameSize > std::numeric_limits<uint16_t>::max ())
220 NS_LOG_WARN ("CsmaNetDevice::SetMtu(): Frame size overflow, MTU not set.");
224 m_frameSize = newFrameSize;
227 NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
228 NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
229 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
235 CsmaNetDevice::GetMtu (void) const
237 NS_LOG_FUNCTION_NOARGS ();
242 CsmaNetDevice::SetFrameSize (uint16_t frameSize)
244 NS_LOG_FUNCTION (frameSize);
246 m_frameSize = frameSize;
247 m_mtu = MtuFromFrameSize (frameSize);
249 NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
250 NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
251 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
255 CsmaNetDevice::GetFrameSize (void) const
261 CsmaNetDevice::SetAddress (Mac48Address self)
263 NS_LOG_FUNCTION (self);
268 CsmaNetDevice::SetSendEnable (bool sendEnable)
270 NS_LOG_FUNCTION (sendEnable);
271 m_sendEnable = sendEnable;
275 CsmaNetDevice::SetReceiveEnable (bool receiveEnable)
277 NS_LOG_FUNCTION (receiveEnable);
278 m_receiveEnable = receiveEnable;
282 CsmaNetDevice::IsSendEnabled (void)
284 NS_LOG_FUNCTION_NOARGS ();
289 CsmaNetDevice::IsReceiveEnabled (void)
291 NS_LOG_FUNCTION_NOARGS ();
292 return m_receiveEnable;
296 CsmaNetDevice::SetInterframeGap (Time t)
299 m_tInterframeGap = t;
303 CsmaNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots, uint32_t ceiling, uint32_t maxRetries)
305 NS_LOG_FUNCTION (slotTime << minSlots << maxSlots << ceiling << maxRetries);
306 m_backoff.m_slotTime = slotTime;
307 m_backoff.m_minSlots = minSlots;
308 m_backoff.m_maxSlots = maxSlots;
309 m_backoff.m_ceiling = ceiling;
310 m_backoff.m_maxRetries = maxRetries;
314 CsmaNetDevice::AddHeader (Ptr<Packet> p, Mac48Address source, Mac48Address dest, uint16_t protocolNumber)
316 NS_LOG_FUNCTION (p << source << dest << protocolNumber);
318 EthernetHeader header (false);
319 header.SetSource (source);
320 header.SetDestination (dest);
322 EthernetTrailer trailer;
324 NS_LOG_LOGIC ("p->GetSize () = " << p->GetSize ());
325 NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
326 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
327 NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
329 uint16_t lengthType = 0;
333 NS_LOG_LOGIC ("Encapsulating packet as DIX (type interpretation)");
335 // This corresponds to the type interpretation of the lengthType field as in the old Ethernet Blue Book.
337 lengthType = protocolNumber;
341 NS_LOG_LOGIC ("Encapsulating packet as LLC (length interpretation)");
344 llc.SetType (protocolNumber);
347 // This corresponds to the length interpretation of the lengthType field,
348 // but with an LLC/SNAP header added to the payload as in IEEE 802.2
350 lengthType = p->GetSize ();
351 NS_ASSERT_MSG (lengthType <= m_frameSize - 18,
352 "CsmaNetDevice::AddHeader(): 802.3 Length/Type field with LLC/SNAP: "
353 "length interpretation must not exceed device frame size minus overhead");
358 NS_FATAL_ERROR ("CsmaNetDevice::AddHeader(): Unknown packet encapsulation mode");
362 NS_LOG_LOGIC ("header.SetLengthType (" << lengthType << ")");
363 header.SetLengthType (lengthType);
364 p->AddHeader (header);
367 p->AddTrailer (trailer);
371 CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
373 NS_LOG_FUNCTION (p << param);
375 EthernetTrailer trailer;
377 p->RemoveTrailer (trailer);
378 trailer.CheckFcs (p);
380 EthernetHeader header (false);
381 p->RemoveHeader (header);
383 if ((header.GetDestination () != GetBroadcast ()) &&
384 (header.GetDestination () != GetAddress ()))
392 param = header.GetLengthType ();
397 p->RemoveHeader (llc);
398 param = llc.GetType ();
403 NS_FATAL_ERROR ("CsmaNetDevice::ProcessHeader(): Unknown packet encapsulation mode");
410 CsmaNetDevice::TransmitStart ()
412 NS_LOG_FUNCTION_NOARGS ();
414 NS_LOG_LOGIC ("m_currentPkt=" << m_currentPkt);
415 NS_LOG_LOGIC ("UID is " << m_currentPkt->GetUid ());
417 // This function is called to start the process of transmitting a packet.
418 // We need to tell the channel that we've started wiggling the wire and
419 // schedule an event that will be executed when it's time to tell the
420 // channel that we're done wiggling the wire.
422 NS_ASSERT_MSG ((m_txMachineState == READY) || (m_txMachineState == BACKOFF),
423 "Must be READY to transmit. Tx state is: " << m_txMachineState);
426 // Only transmit if send side of net device is enabled
428 if (IsSendEnabled () == false)
433 if (m_channel->GetState () != IDLE)
436 // The channel is busy -- backoff and rechedule TransmitStart ()
438 m_txMachineState = BACKOFF;
440 if (m_backoff.MaxRetriesReached ())
443 // Too many retries, abort transmission of packet
449 m_backoff.IncrNumRetries ();
450 Time backoffTime = m_backoff.GetBackoffTime ();
452 NS_LOG_LOGIC ("Channel busy, backing off for " << backoffTime.GetSeconds () << " sec");
454 Simulator::Schedule (backoffTime, &CsmaNetDevice::TransmitStart, this);
460 // The channel is free, transmit the packet
462 m_txMachineState = BUSY;
463 Time tEvent = Seconds (m_bps.CalculateTxTime (m_currentPkt->GetSize ()));
465 NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << tEvent.GetSeconds () << "sec");
467 Simulator::Schedule (tEvent, &CsmaNetDevice::TransmitCompleteEvent, this);
469 if (m_channel->TransmitStart (m_currentPkt, m_deviceId) == false)
471 NS_LOG_WARN ("Channel transmit start did not work at " << tEvent.GetSeconds () << "sec");
472 m_txMachineState = READY;
477 // Transmission succeeded, reset the backoff time parameters.
479 m_backoff.ResetBackoffTime ();
486 CsmaNetDevice::TransmitAbort (void)
488 NS_LOG_FUNCTION_NOARGS ();
490 NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
493 // Since we were transmitting a packet, that packet had better be on the transmit queue.
495 m_currentPkt = m_queue->Dequeue ();
496 NS_ASSERT_MSG (m_currentPkt != 0, "No Packet on queue during CsmaNetDevice::TransmitAbort()");
499 // The last one failed. Let's try to transmit the next one (if there)
501 m_backoff.ResetBackoffTime ();
502 m_txMachineState = READY;
507 CsmaNetDevice::TransmitCompleteEvent (void)
509 NS_LOG_FUNCTION_NOARGS ();
512 // This function is called to finish the process of transmitting a packet.
513 // We need to tell the channel that we've stopped wiggling the wire and
514 // schedule an event that will be executed when it's time to re-enable
515 // the transmitter after the interframe gap.
517 NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
518 NS_ASSERT (m_channel->GetState () == TRANSMITTING);
519 m_txMachineState = GAP;
521 NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
522 m_channel->TransmitEnd ();
524 NS_LOG_LOGIC ("Schedule TransmitReadyEvent in " << m_tInterframeGap.GetSeconds () << "sec");
526 Simulator::Schedule (m_tInterframeGap, &CsmaNetDevice::TransmitReadyEvent, this);
530 CsmaNetDevice::TransmitReadyEvent (void)
532 NS_LOG_FUNCTION_NOARGS ();
535 // This function is called to enable the transmitter after the interframe
536 // gap has passed. If there are pending transmissions, we use this opportunity
537 // to start the next transmit.
539 NS_ASSERT_MSG (m_txMachineState == GAP, "Must be in interframe gap");
540 m_txMachineState = READY;
543 // Get the next packet from the queue for transmitting
545 if (m_queue->IsEmpty ())
551 m_currentPkt = m_queue->Dequeue ();
552 NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitReadyEvent(): IsEmpty false but no Packet on queue?");
558 CsmaNetDevice::Attach (Ptr<CsmaChannel> ch)
560 NS_LOG_FUNCTION (this << &ch);
564 m_deviceId = m_channel->Attach (this);
567 // The channel provides us with the transmitter data rate.
569 m_bps = m_channel->GetDataRate ();
572 // We use the Ethernet interframe gap of 96 bit times.
574 m_tInterframeGap = Seconds (m_bps.CalculateTxTime (96/8));
577 // This device is up whenever a channel is attached to it.
584 CsmaNetDevice::SetQueue (Ptr<Queue> q)
591 CsmaNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
593 NS_LOG_FUNCTION (em);
594 m_receiveErrorModel = em;
598 CsmaNetDevice::Receive (Ptr<Packet> packet, Ptr<CsmaNetDevice> senderDevice)
600 NS_LOG_FUNCTION (packet << senderDevice);
601 NS_LOG_LOGIC ("UID is " << packet->GetUid ());
605 Mac48Address multicast6AllNodes("33:33:00:00:00:01");
606 Mac48Address multicast6AllRouters("33:33:00:00:00:02");
607 Mac48Address multicast6AllHosts("33:33:00:00:00:03");
608 Mac48Address multicast6Node; /* multicast address addressed to our MAC address */
610 /* generate IPv6 multicast ethernet destination that nodes will accept */
611 GetAddress().CopyTo(mac);
615 multicast6Node.CopyFrom(mac);
618 // We never forward up packets that we sent. Real devices don't do this since
619 // their receivers are disabled during send, so we don't. Drop the packet
620 // silently (no tracing) since it would really never get here in a real device.
622 if (senderDevice == this)
628 // Only receive if the send side of net device is enabled
630 if (IsReceiveEnabled () == false)
632 m_dropTrace (packet);
637 // Trace sinks will expect complete packets, not packets without some of the
640 Ptr<Packet> originalPacket = packet->Copy ();
642 EthernetTrailer trailer;
643 packet->RemoveTrailer (trailer);
644 trailer.CheckFcs (packet);
646 EthernetHeader header (false);
647 packet->RemoveHeader (header);
649 NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
650 NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
652 if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
654 NS_LOG_LOGIC ("Dropping pkt due to error model ");
655 m_dropTrace (packet);
660 // variable <protocol> must be initialized to avoid a compiler warning in the RAW case that breaks the optimized build.
662 uint16_t protocol = 0;
667 protocol = header.GetLengthType ();
672 packet->RemoveHeader (llc);
673 protocol = llc.GetType ();
678 NS_FATAL_ERROR ("CsmaNetDevice::Receive(): Unknown packet encapsulation mode");
682 PacketType packetType;
684 if (header.GetDestination ().IsBroadcast ())
686 packetType = PACKET_BROADCAST;
687 m_rxTrace (originalPacket);
689 else if (header.GetDestination ().IsMulticast () ||
690 header.GetDestination() == multicast6Node ||
691 header.GetDestination() == multicast6AllNodes ||
692 header.GetDestination() == multicast6AllRouters ||
693 header.GetDestination() == multicast6AllHosts)
695 packetType = PACKET_MULTICAST;
696 m_rxTrace (originalPacket);
698 else if (header.GetDestination () == m_address)
700 packetType = PACKET_HOST;
701 m_rxTrace (originalPacket);
705 packetType = PACKET_OTHERHOST;
708 if (!m_promiscRxCallback.IsNull ())
710 m_promiscRxCallback (this, packet, protocol, header.GetSource (), header.GetDestination (), packetType);
713 if (packetType != PACKET_OTHERHOST)
715 m_rxCallback (this, packet, protocol, header.GetSource ());
721 CsmaNetDevice::GetQueue (void) const
723 NS_LOG_FUNCTION_NOARGS ();
728 CsmaNetDevice::NotifyLinkUp (void)
730 NS_LOG_FUNCTION_NOARGS ();
733 if (m_linkChangeCallback.IsNull () == false)
735 m_linkChangeCallback ();
740 CsmaNetDevice::SetName (const std::string name)
742 NS_LOG_FUNCTION (name);
747 CsmaNetDevice::GetName (void) const
749 NS_LOG_FUNCTION_NOARGS ();
754 CsmaNetDevice::SetIfIndex (const uint32_t index)
756 NS_LOG_FUNCTION (index);
761 CsmaNetDevice::GetIfIndex (void) const
763 NS_LOG_FUNCTION_NOARGS ();
768 CsmaNetDevice::GetChannel (void) const
770 NS_LOG_FUNCTION_NOARGS ();
775 CsmaNetDevice::GetAddress (void) const
777 NS_LOG_FUNCTION_NOARGS ();
782 CsmaNetDevice::IsLinkUp (void) const
784 NS_LOG_FUNCTION_NOARGS ();
789 CsmaNetDevice::SetLinkChangeCallback (Callback<void> callback)
791 NS_LOG_FUNCTION (&callback);
792 m_linkChangeCallback = callback;
796 CsmaNetDevice::IsBroadcast (void) const
798 NS_LOG_FUNCTION_NOARGS ();
803 CsmaNetDevice::GetBroadcast (void) const
805 NS_LOG_FUNCTION_NOARGS ();
806 return Mac48Address ("ff:ff:ff:ff:ff:ff");
810 CsmaNetDevice::IsMulticast (void) const
812 NS_LOG_FUNCTION_NOARGS ();
817 CsmaNetDevice::GetMulticast (Ipv4Address multicastGroup) const
819 NS_LOG_FUNCTION (multicastGroup);
821 Mac48Address ad = Mac48Address::GetMulticast (multicastGroup);
824 // Implicit conversion (operator Address ()) is defined for Mac48Address, so
825 // use it by just returning the EUI-48 address which is automagically converted
828 NS_LOG_LOGIC ("multicast address is " << ad);
834 CsmaNetDevice::IsPointToPoint (void) const
836 NS_LOG_FUNCTION_NOARGS ();
841 CsmaNetDevice::Send (Ptr<Packet> packet,const Address& dest, uint16_t protocolNumber)
843 NS_LOG_FUNCTION (packet << dest << protocolNumber);
844 return SendFrom (packet, m_address, dest, protocolNumber);
848 CsmaNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
850 NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
851 NS_LOG_LOGIC ("p=" << packet);
852 NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
854 NS_ASSERT (IsLinkUp ());
857 // Only transmit if send side of net device is enabled
859 if (IsSendEnabled () == false)
864 Mac48Address destination = Mac48Address::ConvertFrom (dest);
865 Mac48Address source = Mac48Address::ConvertFrom (src);
866 AddHeader (packet, source, destination, protocolNumber);
869 // Place the packet to be sent on the send queue
871 if (m_queue->Enqueue(packet) == false)
877 // If the device is idle, we need to start a transmission. Otherwise,
878 // the transmission will be started when the current packet finished
879 // transmission (see TransmitCompleteEvent)
881 if (m_txMachineState == READY)
884 // The next packet to be transmitted goes in m_currentPkt
886 m_currentPkt = m_queue->Dequeue ();
887 if (m_currentPkt != 0)
896 CsmaNetDevice::GetNode (void) const
898 NS_LOG_FUNCTION_NOARGS ();
903 CsmaNetDevice::SetNode (Ptr<Node> node)
905 NS_LOG_FUNCTION (node);
909 if (m_name.size () == 0)
911 for (uint32_t i = 0; i < node->GetNDevices (); i++)
913 Ptr<NetDevice> dev = node->GetDevice (i);
914 if (dynamic_cast<CsmaNetDevice*> (PeekPointer (dev)))
923 std::ostringstream s;
930 CsmaNetDevice::NeedsArp (void) const
932 NS_LOG_FUNCTION_NOARGS ();
937 CsmaNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
939 NS_LOG_FUNCTION (&cb);
943 Address CsmaNetDevice::GetMulticast (Ipv6Address addr) const
945 Mac48Address ad = Mac48Address::GetMulticast (addr);
947 NS_LOG_LOGIC("MAC IPv6 multicast address is " << ad);
952 CsmaNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
954 NS_LOG_FUNCTION (&cb);
955 m_promiscRxCallback = cb;
959 CsmaNetDevice::SupportsSendFrom () const
961 NS_LOG_FUNCTION_NOARGS ();