1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "simple-net-device.h"
21 #include "simple-channel.h"
22 #include "ns3/node.h"
23 #include "ns3/packet.h"
24 #include "ns3/log.h"
25 #include "ns3/pointer.h"
26 #include "ns3/error-model.h"
27 #include "ns3/trace-source-accessor.h"
28 #include "ns3/boolean.h"
29 #include "ns3/string.h"
30 #include "ns3/tag.h"
31 #include "ns3/simulator.h"
32 #include "ns3/queue.h"
33 
34 namespace ns3 {
35 
36 NS_LOG_COMPONENT_DEFINE ("SimpleNetDevice");
37 
38 /**
39  * \brief SimpleNetDevice tag to store source, destination and protocol of each packet.
40  */
41 class SimpleTag : public Tag {
42 public:
43   /**
44    * \brief Get the type ID.
45    * \return the object TypeId
46    */
47   static TypeId GetTypeId (void);
48   virtual TypeId GetInstanceTypeId (void) const;
49 
50   virtual uint32_t GetSerializedSize (void) const;
51   virtual void Serialize (TagBuffer i) const;
52   virtual void Deserialize (TagBuffer i);
53 
54   /**
55    * Set the source address
56    * \param src source address
57    */
58   void SetSrc (Mac48Address src);
59   /**
60    * Get the source address
61    * \return the source address
62    */
63   Mac48Address GetSrc (void) const;
64 
65   /**
66    * Set the destination address
67    * \param dst destination address
68    */
69   void SetDst (Mac48Address dst);
70   /**
71    * Get the destination address
72    * \return the destination address
73    */
74   Mac48Address GetDst (void) const;
75 
76   /**
77    * Set the protocol number
78    * \param proto protocol number
79    */
80   void SetProto (uint16_t proto);
81   /**
82    * Get the protocol number
83    * \return the protocol number
84    */
85   uint16_t GetProto (void) const;
86 
87   void Print (std::ostream &os) const;
88 
89 private:
90   Mac48Address m_src; //!< source address
91   Mac48Address m_dst; //!< destination address
92   uint16_t m_protocolNumber; //!< protocol number
93 };
94 
95 
96 NS_OBJECT_ENSURE_REGISTERED (SimpleTag);
97 
98 TypeId
GetTypeId(void)99 SimpleTag::GetTypeId (void)
100 {
101   static TypeId tid = TypeId ("ns3::SimpleTag")
102     .SetParent<Tag> ()
103     .SetGroupName("Network")
104     .AddConstructor<SimpleTag> ()
105   ;
106   return tid;
107 }
108 TypeId
GetInstanceTypeId(void) const109 SimpleTag::GetInstanceTypeId (void) const
110 {
111   return GetTypeId ();
112 }
113 
114 uint32_t
GetSerializedSize(void) const115 SimpleTag::GetSerializedSize (void) const
116 {
117   return 8+8+2;
118 }
119 void
Serialize(TagBuffer i) const120 SimpleTag::Serialize (TagBuffer i) const
121 {
122   uint8_t mac[6];
123   m_src.CopyTo (mac);
124   i.Write (mac, 6);
125   m_dst.CopyTo (mac);
126   i.Write (mac, 6);
127   i.WriteU16 (m_protocolNumber);
128 }
129 void
Deserialize(TagBuffer i)130 SimpleTag::Deserialize (TagBuffer i)
131 {
132   uint8_t mac[6];
133   i.Read (mac, 6);
134   m_src.CopyFrom (mac);
135   i.Read (mac, 6);
136   m_dst.CopyFrom (mac);
137   m_protocolNumber = i.ReadU16 ();
138 }
139 
140 void
SetSrc(Mac48Address src)141 SimpleTag::SetSrc (Mac48Address src)
142 {
143   m_src = src;
144 }
145 
146 Mac48Address
GetSrc(void) const147 SimpleTag::GetSrc (void) const
148 {
149   return m_src;
150 }
151 
152 void
SetDst(Mac48Address dst)153 SimpleTag::SetDst (Mac48Address dst)
154 {
155   m_dst = dst;
156 }
157 
158 Mac48Address
GetDst(void) const159 SimpleTag::GetDst (void) const
160 {
161   return m_dst;
162 }
163 
164 void
SetProto(uint16_t proto)165 SimpleTag::SetProto (uint16_t proto)
166 {
167   m_protocolNumber = proto;
168 }
169 
170 uint16_t
GetProto(void) const171 SimpleTag::GetProto (void) const
172 {
173   return m_protocolNumber;
174 }
175 
176 void
Print(std::ostream & os) const177 SimpleTag::Print (std::ostream &os) const
178 {
179   os << "src=" << m_src << " dst=" << m_dst << " proto=" << m_protocolNumber;
180 }
181 
182 
183 
184 NS_OBJECT_ENSURE_REGISTERED (SimpleNetDevice);
185 
186 TypeId
GetTypeId(void)187 SimpleNetDevice::GetTypeId (void)
188 {
189   static TypeId tid = TypeId ("ns3::SimpleNetDevice")
190     .SetParent<NetDevice> ()
191     .SetGroupName("Network")
192     .AddConstructor<SimpleNetDevice> ()
193     .AddAttribute ("ReceiveErrorModel",
194                    "The receiver error model used to simulate packet loss",
195                    PointerValue (),
196                    MakePointerAccessor (&SimpleNetDevice::m_receiveErrorModel),
197                    MakePointerChecker<ErrorModel> ())
198     .AddAttribute ("PointToPointMode",
199                    "The device is configured in Point to Point mode",
200                    BooleanValue (false),
201                    MakeBooleanAccessor (&SimpleNetDevice::m_pointToPointMode),
202                    MakeBooleanChecker ())
203     .AddAttribute ("TxQueue",
204                    "A queue to use as the transmit queue in the device.",
205                    StringValue ("ns3::DropTailQueue<Packet>"),
206                    MakePointerAccessor (&SimpleNetDevice::m_queue),
207                    MakePointerChecker<Queue<Packet> > ())
208     .AddAttribute ("DataRate",
209                    "The default data rate for point to point links. Zero means infinite",
210                    DataRateValue (DataRate ("0b/s")),
211                    MakeDataRateAccessor (&SimpleNetDevice::m_bps),
212                    MakeDataRateChecker ())
213     .AddTraceSource ("PhyRxDrop",
214                      "Trace source indicating a packet has been dropped "
215                      "by the device during reception",
216                      MakeTraceSourceAccessor (&SimpleNetDevice::m_phyRxDropTrace),
217                      "ns3::Packet::TracedCallback")
218   ;
219   return tid;
220 }
221 
SimpleNetDevice()222 SimpleNetDevice::SimpleNetDevice ()
223   : m_channel (0),
224     m_node (0),
225     m_mtu (0xffff),
226     m_ifIndex (0),
227     m_linkUp (false)
228 {
229   NS_LOG_FUNCTION (this);
230 }
231 
232 void
Receive(Ptr<Packet> packet,uint16_t protocol,Mac48Address to,Mac48Address from)233 SimpleNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol,
234                           Mac48Address to, Mac48Address from)
235 {
236   NS_LOG_FUNCTION (this << packet << protocol << to << from);
237   NetDevice::PacketType packetType;
238 
239   if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
240     {
241       m_phyRxDropTrace (packet);
242       return;
243     }
244 
245   if (to == m_address)
246     {
247       packetType = NetDevice::PACKET_HOST;
248     }
249   else if (to.IsBroadcast ())
250     {
251       packetType = NetDevice::PACKET_BROADCAST;
252     }
253   else if (to.IsGroup ())
254     {
255       packetType = NetDevice::PACKET_MULTICAST;
256     }
257   else
258     {
259       packetType = NetDevice::PACKET_OTHERHOST;
260     }
261 
262   if (packetType != NetDevice::PACKET_OTHERHOST)
263     {
264       m_rxCallback (this, packet, protocol, from);
265     }
266 
267   if (!m_promiscCallback.IsNull ())
268     {
269       m_promiscCallback (this, packet, protocol, from, to, packetType);
270     }
271 }
272 
273 void
SetChannel(Ptr<SimpleChannel> channel)274 SimpleNetDevice::SetChannel (Ptr<SimpleChannel> channel)
275 {
276   NS_LOG_FUNCTION (this << channel);
277   m_channel = channel;
278   m_channel->Add (this);
279   m_linkUp = true;
280   m_linkChangeCallbacks ();
281 }
282 
283 Ptr<Queue<Packet> >
GetQueue() const284 SimpleNetDevice::GetQueue () const
285 {
286   NS_LOG_FUNCTION (this);
287   return m_queue;
288 }
289 
290 void
SetQueue(Ptr<Queue<Packet>> q)291 SimpleNetDevice::SetQueue (Ptr<Queue<Packet> > q)
292 {
293   NS_LOG_FUNCTION (this << q);
294   m_queue = q;
295 }
296 
297 void
SetReceiveErrorModel(Ptr<ErrorModel> em)298 SimpleNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
299 {
300   NS_LOG_FUNCTION (this << em);
301   m_receiveErrorModel = em;
302 }
303 
304 void
SetIfIndex(const uint32_t index)305 SimpleNetDevice::SetIfIndex (const uint32_t index)
306 {
307   NS_LOG_FUNCTION (this << index);
308   m_ifIndex = index;
309 }
310 uint32_t
GetIfIndex(void) const311 SimpleNetDevice::GetIfIndex (void) const
312 {
313   NS_LOG_FUNCTION (this);
314   return m_ifIndex;
315 }
316 Ptr<Channel>
GetChannel(void) const317 SimpleNetDevice::GetChannel (void) const
318 {
319   NS_LOG_FUNCTION (this);
320   return m_channel;
321 }
322 void
SetAddress(Address address)323 SimpleNetDevice::SetAddress (Address address)
324 {
325   NS_LOG_FUNCTION (this << address);
326   m_address = Mac48Address::ConvertFrom (address);
327 }
328 Address
GetAddress(void) const329 SimpleNetDevice::GetAddress (void) const
330 {
331   //
332   // Implicit conversion from Mac48Address to Address
333   //
334   NS_LOG_FUNCTION (this);
335   return m_address;
336 }
337 bool
SetMtu(const uint16_t mtu)338 SimpleNetDevice::SetMtu (const uint16_t mtu)
339 {
340   NS_LOG_FUNCTION (this << mtu);
341   m_mtu = mtu;
342   return true;
343 }
344 uint16_t
GetMtu(void) const345 SimpleNetDevice::GetMtu (void) const
346 {
347   NS_LOG_FUNCTION (this);
348   return m_mtu;
349 }
350 bool
IsLinkUp(void) const351 SimpleNetDevice::IsLinkUp (void) const
352 {
353   NS_LOG_FUNCTION (this);
354   return m_linkUp;
355 }
356 void
AddLinkChangeCallback(Callback<void> callback)357 SimpleNetDevice::AddLinkChangeCallback (Callback<void> callback)
358 {
359  NS_LOG_FUNCTION (this << &callback);
360  m_linkChangeCallbacks.ConnectWithoutContext (callback);
361 }
362 bool
IsBroadcast(void) const363 SimpleNetDevice::IsBroadcast (void) const
364 {
365   NS_LOG_FUNCTION (this);
366   if (m_pointToPointMode)
367     {
368       return false;
369     }
370   return true;
371 }
372 Address
GetBroadcast(void) const373 SimpleNetDevice::GetBroadcast (void) const
374 {
375   NS_LOG_FUNCTION (this);
376   return Mac48Address ("ff:ff:ff:ff:ff:ff");
377 }
378 bool
IsMulticast(void) const379 SimpleNetDevice::IsMulticast (void) const
380 {
381   NS_LOG_FUNCTION (this);
382   if (m_pointToPointMode)
383     {
384       return false;
385     }
386   return true;
387 }
388 Address
GetMulticast(Ipv4Address multicastGroup) const389 SimpleNetDevice::GetMulticast (Ipv4Address multicastGroup) const
390 {
391   NS_LOG_FUNCTION (this << multicastGroup);
392   return Mac48Address::GetMulticast (multicastGroup);
393 }
394 
GetMulticast(Ipv6Address addr) const395 Address SimpleNetDevice::GetMulticast (Ipv6Address addr) const
396 {
397   NS_LOG_FUNCTION (this << addr);
398   return Mac48Address::GetMulticast (addr);
399 }
400 
401 bool
IsPointToPoint(void) const402 SimpleNetDevice::IsPointToPoint (void) const
403 {
404   NS_LOG_FUNCTION (this);
405   if (m_pointToPointMode)
406     {
407       return true;
408     }
409   return false;
410 }
411 
412 bool
IsBridge(void) const413 SimpleNetDevice::IsBridge (void) const
414 {
415   NS_LOG_FUNCTION (this);
416   return false;
417 }
418 
419 bool
Send(Ptr<Packet> packet,const Address & dest,uint16_t protocolNumber)420 SimpleNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
421 {
422   NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
423 
424   return SendFrom (packet, m_address, dest, protocolNumber);
425 }
426 
427 bool
SendFrom(Ptr<Packet> p,const Address & source,const Address & dest,uint16_t protocolNumber)428 SimpleNetDevice::SendFrom (Ptr<Packet> p, const Address& source, const Address& dest, uint16_t protocolNumber)
429 {
430   NS_LOG_FUNCTION (this << p << source << dest << protocolNumber);
431   if (p->GetSize () > GetMtu ())
432     {
433       return false;
434     }
435 
436   Mac48Address to = Mac48Address::ConvertFrom (dest);
437   Mac48Address from = Mac48Address::ConvertFrom (source);
438 
439   SimpleTag tag;
440   tag.SetSrc (from);
441   tag.SetDst (to);
442   tag.SetProto (protocolNumber);
443 
444   p->AddPacketTag (tag);
445 
446   if (m_queue->Enqueue (p))
447     {
448       if (m_queue->GetNPackets () == 1 && !FinishTransmissionEvent.IsRunning ())
449         {
450           StartTransmission ();
451         }
452       return true;
453     }
454 
455   return false;
456 }
457 
458 void
StartTransmission()459 SimpleNetDevice::StartTransmission ()
460 {
461   if (m_queue->GetNPackets () == 0)
462     {
463       return;
464     }
465   NS_ASSERT_MSG (!FinishTransmissionEvent.IsRunning (),
466                  "Tried to transmit a packet while another transmission was in progress");
467   Ptr<Packet> packet = m_queue->Dequeue ();
468 
469   /**
470    * SimpleChannel will deliver the packet to the far end(s) of the link as soon as Send is called
471    * (or after its fixed delay, if one is configured). So we have to handle the rate of the link here,
472    * which we do by scheduling FinishTransmission (packetSize / linkRate) time in the future. While
473    * that event is running, the transmit path of this NetDevice is busy, so we can't send other packets.
474    *
475    * SimpleChannel doesn't have a locking mechanism, and doesn't check for collisions, so there's nothing
476    * we need to do with the channel until the transmission has "completed" from the perspective of this
477    * NetDevice.
478    */
479   Time txTime = Time (0);
480   if (m_bps > DataRate (0))
481     {
482       txTime = m_bps.CalculateBytesTxTime (packet->GetSize ());
483     }
484   FinishTransmissionEvent = Simulator::Schedule (txTime, &SimpleNetDevice::FinishTransmission, this, packet);
485 }
486 
487 void
FinishTransmission(Ptr<Packet> packet)488 SimpleNetDevice::FinishTransmission (Ptr<Packet> packet)
489 {
490   NS_LOG_FUNCTION (this);
491 
492   SimpleTag tag;
493   packet->RemovePacketTag (tag);
494 
495   Mac48Address src = tag.GetSrc ();
496   Mac48Address dst = tag.GetDst ();
497   uint16_t proto = tag.GetProto ();
498 
499   m_channel->Send (packet, proto, dst, src, this);
500 
501   StartTransmission ();
502 
503   return;
504 }
505 
506 Ptr<Node>
GetNode(void) const507 SimpleNetDevice::GetNode (void) const
508 {
509   NS_LOG_FUNCTION (this);
510   return m_node;
511 }
512 void
SetNode(Ptr<Node> node)513 SimpleNetDevice::SetNode (Ptr<Node> node)
514 {
515   NS_LOG_FUNCTION (this << node);
516   m_node = node;
517 }
518 bool
NeedsArp(void) const519 SimpleNetDevice::NeedsArp (void) const
520 {
521   NS_LOG_FUNCTION (this);
522   if (m_pointToPointMode)
523     {
524       return false;
525     }
526   return true;
527 }
528 void
SetReceiveCallback(NetDevice::ReceiveCallback cb)529 SimpleNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
530 {
531   NS_LOG_FUNCTION (this << &cb);
532   m_rxCallback = cb;
533 }
534 
535 void
DoDispose(void)536 SimpleNetDevice::DoDispose (void)
537 {
538   NS_LOG_FUNCTION (this);
539   m_channel = 0;
540   m_node = 0;
541   m_receiveErrorModel = 0;
542   m_queue->Dispose ();
543   if (FinishTransmissionEvent.IsRunning ())
544     {
545       FinishTransmissionEvent.Cancel ();
546     }
547   NetDevice::DoDispose ();
548 }
549 
550 
551 void
SetPromiscReceiveCallback(PromiscReceiveCallback cb)552 SimpleNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
553 {
554   NS_LOG_FUNCTION (this << &cb);
555   m_promiscCallback = cb;
556 }
557 
558 bool
SupportsSendFrom(void) const559 SimpleNetDevice::SupportsSendFrom (void) const
560 {
561   NS_LOG_FUNCTION (this);
562   return true;
563 }
564 
565 } // namespace ns3
566