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