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