1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 CTTC
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: Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/queue.h"
23 #include "ns3/simulator.h"
24 #include "ns3/enum.h"
25 #include "ns3/boolean.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/pointer.h"
28 #include "ns3/channel.h"
29 #include "ns3/trace-source-accessor.h"
30 #include "aloha-noack-mac-header.h"
31 #include "aloha-noack-net-device.h"
32 #include "ns3/llc-snap-header.h"
33 
34 namespace ns3 {
35 
36 NS_LOG_COMPONENT_DEFINE ("AlohaNoackNetDevice");
37 
38 /**
39  * \brief Output stream operator
40  * \param os output stream
41  * \param state the state to print
42  * \return an output stream
43  */
operator <<(std::ostream & os,AlohaNoackNetDevice::State state)44 std::ostream& operator<< (std::ostream& os, AlohaNoackNetDevice::State state)
45 {
46   switch (state)
47     {
48     case AlohaNoackNetDevice::IDLE:
49       os << "IDLE";
50       break;
51     case AlohaNoackNetDevice::TX:
52       os << "TX";
53       break;
54     case AlohaNoackNetDevice::RX:
55       os << "RX";
56       break;
57     }
58   return os;
59 }
60 
61 
62 NS_OBJECT_ENSURE_REGISTERED (AlohaNoackNetDevice);
63 
64 TypeId
GetTypeId(void)65 AlohaNoackNetDevice::GetTypeId (void)
66 {
67   static TypeId tid = TypeId ("ns3::AlohaNoackNetDevice")
68     .SetParent<NetDevice> ()
69     .SetGroupName ("Spectrum")
70     .AddConstructor<AlohaNoackNetDevice> ()
71     .AddAttribute ("Address",
72                    "The MAC address of this device.",
73                    Mac48AddressValue (Mac48Address ("12:34:56:78:90:12")),
74                    MakeMac48AddressAccessor (&AlohaNoackNetDevice::m_address),
75                    MakeMac48AddressChecker ())
76     .AddAttribute ("Queue",
77                    "packets being transmitted get queued here",
78                    PointerValue (),
79                    MakePointerAccessor (&AlohaNoackNetDevice::m_queue),
80                    MakePointerChecker<Queue<Packet> > ())
81     .AddAttribute ("Mtu", "The Maximum Transmission Unit",
82                    UintegerValue (1500),
83                    MakeUintegerAccessor (&AlohaNoackNetDevice::SetMtu,
84                                          &AlohaNoackNetDevice::GetMtu),
85                    MakeUintegerChecker<uint16_t> (1,65535))
86     .AddAttribute ("Phy", "The PHY layer attached to this device.",
87                    PointerValue (),
88                    MakePointerAccessor (&AlohaNoackNetDevice::GetPhy,
89                                         &AlohaNoackNetDevice::SetPhy),
90                    MakePointerChecker<Object> ())
91     .AddTraceSource ("MacTx",
92                      "Trace source indicating a packet has arrived "
93                      "for transmission by this device",
94                      MakeTraceSourceAccessor (&AlohaNoackNetDevice::m_macTxTrace),
95                      "ns3::Packet::TracedCallback")
96     .AddTraceSource ("MacTxDrop",
97                      "Trace source indicating a packet has been dropped "
98                      "by the device before transmission",
99                      MakeTraceSourceAccessor (&AlohaNoackNetDevice::m_macTxDropTrace),
100                      "ns3::Packet::TracedCallback")
101     .AddTraceSource ("MacPromiscRx",
102                      "A packet has been received by this device, has been "
103                      "passed up from the physical layer "
104                      "and is being forwarded up the local protocol stack.  "
105                      "This is a promiscuous trace,",
106                      MakeTraceSourceAccessor (&AlohaNoackNetDevice::m_macPromiscRxTrace),
107                      "ns3::Packet::TracedCallback")
108     .AddTraceSource ("MacRx",
109                      "A packet has been received by this device, "
110                      "has been passed up from the physical layer "
111                      "and is being forwarded up the local protocol stack.  "
112                      "This is a non-promiscuous trace,",
113                      MakeTraceSourceAccessor (&AlohaNoackNetDevice::m_macRxTrace),
114                      "ns3::Packet::TracedCallback")
115   ;
116   return tid;
117 }
118 
AlohaNoackNetDevice()119 AlohaNoackNetDevice::AlohaNoackNetDevice ()
120   : m_state (IDLE)
121 {
122   NS_LOG_FUNCTION (this);
123 }
124 
~AlohaNoackNetDevice()125 AlohaNoackNetDevice::~AlohaNoackNetDevice ()
126 {
127   NS_LOG_FUNCTION (this);
128   m_queue = 0;
129 }
130 
131 void
DoDispose()132 AlohaNoackNetDevice::DoDispose ()
133 {
134   NS_LOG_FUNCTION (this);
135   m_queue = 0;
136   m_node = 0;
137   m_channel = 0;
138   m_currentPkt = 0;
139   m_phy = 0;
140   m_phyMacTxStartCallback = MakeNullCallback< bool, Ptr<Packet> > ();
141   NetDevice::DoDispose ();
142 }
143 
144 
145 void
SetIfIndex(const uint32_t index)146 AlohaNoackNetDevice::SetIfIndex (const uint32_t index)
147 {
148   NS_LOG_FUNCTION (index);
149   m_ifIndex = index;
150 }
151 
152 uint32_t
GetIfIndex(void) const153 AlohaNoackNetDevice::GetIfIndex (void) const
154 {
155   NS_LOG_FUNCTION (this);
156   return m_ifIndex;
157 }
158 
159 bool
SetMtu(uint16_t mtu)160 AlohaNoackNetDevice::SetMtu (uint16_t mtu)
161 {
162   NS_LOG_FUNCTION (mtu);
163   m_mtu = mtu;
164   return true;
165 }
166 
167 uint16_t
GetMtu(void) const168 AlohaNoackNetDevice::GetMtu (void) const
169 {
170   NS_LOG_FUNCTION (this);
171   return m_mtu;
172 }
173 
174 
175 void
SetQueue(Ptr<Queue<Packet>> q)176 AlohaNoackNetDevice::SetQueue (Ptr<Queue<Packet> > q)
177 {
178   NS_LOG_FUNCTION (q);
179   m_queue = q;
180 }
181 
182 
183 void
SetAddress(Address address)184 AlohaNoackNetDevice::SetAddress (Address address)
185 {
186   NS_LOG_FUNCTION (this);
187   m_address = Mac48Address::ConvertFrom (address);
188 }
189 
190 Address
GetAddress(void) const191 AlohaNoackNetDevice::GetAddress (void) const
192 {
193   NS_LOG_FUNCTION (this);
194   return m_address;
195 }
196 
197 bool
IsBroadcast(void) const198 AlohaNoackNetDevice::IsBroadcast (void) const
199 {
200   NS_LOG_FUNCTION (this);
201   return true;
202 }
203 
204 Address
GetBroadcast(void) const205 AlohaNoackNetDevice::GetBroadcast (void) const
206 {
207   NS_LOG_FUNCTION (this);
208   return Mac48Address ("ff:ff:ff:ff:ff:ff");
209 }
210 
211 bool
IsMulticast(void) const212 AlohaNoackNetDevice::IsMulticast (void) const
213 {
214   NS_LOG_FUNCTION (this);
215   return true;
216 }
217 
218 Address
GetMulticast(Ipv4Address addr) const219 AlohaNoackNetDevice::GetMulticast (Ipv4Address addr) const
220 {
221   NS_LOG_FUNCTION (addr);
222   Mac48Address ad = Mac48Address::GetMulticast (addr);
223   return ad;
224 }
225 
226 
GetMulticast(Ipv6Address addr) const227 Address AlohaNoackNetDevice::GetMulticast (Ipv6Address addr) const
228 {
229   NS_LOG_FUNCTION (addr);
230   Mac48Address ad = Mac48Address::GetMulticast (addr);
231   return ad;
232 }
233 
234 
235 bool
IsPointToPoint(void) const236 AlohaNoackNetDevice::IsPointToPoint (void) const
237 {
238   NS_LOG_FUNCTION (this);
239   return false;
240 }
241 
242 bool
IsBridge(void) const243 AlohaNoackNetDevice::IsBridge (void) const
244 {
245   NS_LOG_FUNCTION (this);
246   return false;
247 }
248 
249 
250 Ptr<Node>
GetNode(void) const251 AlohaNoackNetDevice::GetNode (void) const
252 {
253   NS_LOG_FUNCTION (this);
254   return m_node;
255 }
256 
257 void
SetNode(Ptr<Node> node)258 AlohaNoackNetDevice::SetNode (Ptr<Node> node)
259 {
260   NS_LOG_FUNCTION (node);
261 
262   m_node = node;
263 }
264 
265 void
SetPhy(Ptr<Object> phy)266 AlohaNoackNetDevice::SetPhy (Ptr<Object> phy)
267 {
268   NS_LOG_FUNCTION (this << phy);
269   m_phy = phy;
270 }
271 
272 
273 Ptr<Object>
GetPhy() const274 AlohaNoackNetDevice::GetPhy () const
275 {
276   NS_LOG_FUNCTION (this);
277   return m_phy;
278 }
279 
280 
281 void
SetChannel(Ptr<Channel> c)282 AlohaNoackNetDevice::SetChannel (Ptr<Channel> c)
283 {
284   NS_LOG_FUNCTION (this << c);
285   m_channel = c;
286 }
287 
288 
289 Ptr<Channel>
GetChannel(void) const290 AlohaNoackNetDevice::GetChannel (void) const
291 {
292   NS_LOG_FUNCTION (this);
293   return m_channel;
294 }
295 
296 
297 bool
NeedsArp(void) const298 AlohaNoackNetDevice::NeedsArp (void) const
299 {
300   NS_LOG_FUNCTION (this);
301   return true;
302 }
303 
304 bool
IsLinkUp(void) const305 AlohaNoackNetDevice::IsLinkUp (void) const
306 {
307   NS_LOG_FUNCTION (this);
308   return m_linkUp;
309 }
310 
311 void
AddLinkChangeCallback(Callback<void> callback)312 AlohaNoackNetDevice::AddLinkChangeCallback (Callback<void> callback)
313 {
314   NS_LOG_FUNCTION (&callback);
315   m_linkChangeCallbacks.ConnectWithoutContext (callback);
316 }
317 
318 void
SetReceiveCallback(NetDevice::ReceiveCallback cb)319 AlohaNoackNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
320 {
321   NS_LOG_FUNCTION (&cb);
322   m_rxCallback = cb;
323 }
324 
325 void
SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)326 AlohaNoackNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
327 {
328   NS_LOG_FUNCTION (&cb);
329   m_promiscRxCallback = cb;
330 }
331 
332 bool
SupportsSendFrom() const333 AlohaNoackNetDevice::SupportsSendFrom () const
334 {
335   NS_LOG_FUNCTION (this);
336   return true;
337 }
338 
339 
340 bool
Send(Ptr<Packet> packet,const Address & dest,uint16_t protocolNumber)341 AlohaNoackNetDevice::Send (Ptr<Packet> packet,const Address& dest, uint16_t protocolNumber)
342 {
343   NS_LOG_FUNCTION (packet << dest << protocolNumber);
344   return SendFrom (packet, m_address, dest, protocolNumber);
345 }
346 
347 bool
SendFrom(Ptr<Packet> packet,const Address & src,const Address & dest,uint16_t protocolNumber)348 AlohaNoackNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
349 {
350   NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
351 
352   LlcSnapHeader llc;
353   llc.SetType (protocolNumber);
354   packet->AddHeader (llc);
355 
356   AlohaNoackMacHeader header;
357   header.SetSource (Mac48Address::ConvertFrom (src));
358   header.SetDestination (Mac48Address::ConvertFrom (dest));
359   packet->AddHeader (header);
360 
361   m_macTxTrace (packet);
362 
363 
364   bool sendOk = true;
365   //
366   // If the device is idle, transmission starts immediately. Otherwise,
367   // the transmission will be started by NotifyTransmissionEnd
368   //
369   NS_LOG_LOGIC (this << " state=" << m_state);
370   if (m_state == IDLE)
371     {
372       if (m_queue->IsEmpty ())
373         {
374           NS_LOG_LOGIC ("new packet is head of queue, starting TX immediately");
375           m_currentPkt = packet;
376           StartTransmission ();
377         }
378       else
379         {
380           NS_LOG_LOGIC ("enqueueing new packet");
381           if (m_queue->Enqueue (packet) == false)
382             {
383               m_macTxDropTrace (packet);
384               sendOk = false;
385             }
386         }
387     }
388   else
389     {
390       NS_LOG_LOGIC ("deferring TX, enqueueing new packet");
391       NS_ASSERT (m_queue);
392       if (m_queue->Enqueue (packet) == false)
393         {
394           m_macTxDropTrace (packet);
395           sendOk = false;
396         }
397     }
398   return sendOk;
399 }
400 
401 void
SetGenericPhyTxStartCallback(GenericPhyTxStartCallback c)402 AlohaNoackNetDevice::SetGenericPhyTxStartCallback (GenericPhyTxStartCallback c)
403 {
404   NS_LOG_FUNCTION (this);
405   m_phyMacTxStartCallback = c;
406 }
407 
408 void
StartTransmission()409 AlohaNoackNetDevice::StartTransmission ()
410 {
411   NS_LOG_FUNCTION (this);
412 
413   NS_ASSERT (m_currentPkt != 0);
414   NS_ASSERT (m_state == IDLE);
415 
416   if (m_phyMacTxStartCallback (m_currentPkt))
417     {
418       NS_LOG_WARN ("PHY refused to start TX");
419     }
420   else
421     {
422       m_state = TX;
423     }
424 }
425 
426 
427 
428 void
NotifyTransmissionEnd(Ptr<const Packet>)429 AlohaNoackNetDevice::NotifyTransmissionEnd (Ptr<const Packet>)
430 {
431   NS_LOG_FUNCTION (this);
432   NS_ASSERT_MSG (m_state == TX, "TX end notified while state != TX");
433   m_state = IDLE;
434   NS_ASSERT (m_queue);
435   if (m_queue->IsEmpty () == false)
436     {
437       Ptr<Packet> p = m_queue->Dequeue ();
438       NS_ASSERT (p);
439       m_currentPkt = p;
440       NS_LOG_LOGIC ("scheduling transmission now");
441       Simulator::ScheduleNow (&AlohaNoackNetDevice::StartTransmission, this);
442     }
443 }
444 
445 
446 void
NotifyReceptionStart()447 AlohaNoackNetDevice::NotifyReceptionStart ()
448 {
449   NS_LOG_FUNCTION (this);
450 }
451 
452 
453 
454 void
NotifyReceptionEndError()455 AlohaNoackNetDevice::NotifyReceptionEndError ()
456 {
457   NS_LOG_FUNCTION (this);
458 }
459 
460 
461 
462 
463 
464 void
NotifyReceptionEndOk(Ptr<Packet> packet)465 AlohaNoackNetDevice::NotifyReceptionEndOk (Ptr<Packet> packet)
466 {
467   NS_LOG_FUNCTION (this << packet);
468   AlohaNoackMacHeader header;
469   packet->RemoveHeader (header);
470   NS_LOG_LOGIC ("packet " << header.GetSource () << " --> " << header.GetDestination () << " (here: " << m_address << ")");
471 
472   LlcSnapHeader llc;
473   packet->RemoveHeader (llc);
474 
475   PacketType packetType;
476   if (header.GetDestination ().IsBroadcast ())
477     {
478       packetType = PACKET_BROADCAST;
479     }
480   else if (header.GetDestination ().IsGroup ())
481     {
482       packetType = PACKET_MULTICAST;
483     }
484   else if (header.GetDestination () == m_address)
485     {
486       packetType = PACKET_HOST;
487     }
488   else
489     {
490       packetType = PACKET_OTHERHOST;
491     }
492 
493   NS_LOG_LOGIC ("packet type = " << packetType);
494 
495   if (!m_promiscRxCallback.IsNull ())
496     {
497       m_promiscRxCallback (this, packet->Copy (), llc.GetType (), header.GetSource (), header.GetDestination (), packetType);
498     }
499 
500   if (packetType != PACKET_OTHERHOST)
501     {
502       m_rxCallback (this, packet, llc.GetType (), header.GetSource () );
503     }
504 }
505 
506 
507 
508 } // namespace ns3
509