Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |
2 /* | |
3 * Copyright (c) 2013 Mohammed J.F. Alenazi | |
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: Mohammed J.F. Alenazi <malenazi@ittc.ku.edu> | |
19 * | |
20 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director | |
21 * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets | |
22 * Information and Telecommunication Technology Center (ITTC) | |
23 * and Department of Electrical Engineering and Computer Science | |
24 * The University of Kansas Lawrence, KS USA. | |
25 * | |
26 * Work supported by King Saud University and the ITTC at The University of Kans as. | |
27 */ | |
28 | |
29 | |
30 #include "epidemic-routing-protocol.h" | |
31 #include <vector> | |
32 #include "ns3/boolean.h" | |
33 #include "ns3/config.h" | |
34 #include "ns3/log.h" | |
35 #include "ns3/random-variable.h" | |
Tom Henderson
2013/12/08 22:24:26
random-variable.h is deprecated; you need to use r
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
36 #include "ns3/inet-socket-address.h" | |
37 #include "ns3/trace-source-accessor.h" | |
Tom Henderson
2013/12/08 22:24:26
you have no trace sources. Adding trace sources m
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
38 #include "ns3/udp-socket-factory.h" | |
39 #include "ns3/wifi-net-device.h" | |
Tom Henderson
2013/12/08 22:24:26
why does the routing protocol depend on wifi-net-d
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
40 #include "ns3/boolean.h" | |
41 #include "ns3/double.h" | |
42 #include "ns3/uinteger.h" | |
43 #include "ns3/udp-header.h" | |
44 #include <iostream> | |
45 #include <algorithm> | |
46 #include <functional> | |
47 #include "ns3/ipv4-route.h" | |
48 #include "ns3/socket.h" | |
49 #include "ns3/log.h" | |
50 | |
51 | |
52 using namespace std; | |
53 | |
54 namespace ns3 { | |
55 namespace epidemic { | |
56 NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol); | |
57 NS_LOG_COMPONENT_DEFINE ("EpidemicRoutingProtocol"); | |
58 | |
59 | |
60 TypeId RoutingProtocol::GetTypeId (void) | |
61 { | |
62 static TypeId tid = TypeId ("ns3::epidemic::RoutingProtocol") | |
63 .SetParent<Ipv4RoutingProtocol> () | |
64 .AddConstructor<RoutingProtocol> () | |
65 .AddAttribute ("HopCount","Maximum number of times a packet will be flooded. ", | |
66 UintegerValue (64), | |
67 MakeUintegerAccessor (&RoutingProtocol::m_HopCount), | |
68 MakeUintegerChecker<uint32_t> ()) | |
69 .AddAttribute ("QueueLength","Maximum number of packets that a queue can hol d.", | |
70 UintegerValue (64), | |
71 MakeUintegerAccessor (&RoutingProtocol::m_maxQueueLen), | |
72 MakeUintegerChecker<uint32_t> ()) | |
73 .AddAttribute ("QueueEntryExpireTime","Time in seconds after which a packet in the queue will expire.", | |
Tom Henderson
2013/12/08 22:24:26
Time after enqueuing on the local node, or time af
mjf.alenazi
2013/12/30 23:11:11
Time after enqueuing on the local node or the pack
| |
74 TimeValue (Seconds (100)), | |
75 MakeTimeAccessor (&RoutingProtocol::m_queueEntryExpireTime), | |
76 MakeTimeChecker ()) | |
77 .AddAttribute ("BeaconInterval","Time in seconds after which a beacon packet is broadcast.", | |
Tom Henderson
2013/12/08 22:24:26
Mean time, or exact time?
mjf.alenazi
2013/12/30 23:11:11
Time specified in seconds + some milliseconds to a
| |
78 TimeValue (Seconds (1)), | |
79 MakeTimeAccessor (&RoutingProtocol::m_beaconInterval), | |
80 MakeTimeChecker ()); | |
81 return tid; | |
82 } | |
83 | |
84 | |
85 | |
86 // define this class in a public header | |
Tom Henderson
2013/12/08 22:24:26
move the class declaration to a header, as you sug
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
87 | |
88 //----------------------------------------------------------------------------- | |
89 /// Tag used by epidemic implementation | |
90 | |
91 class EpidemicTag : public Tag | |
92 { | |
93 | |
94 public: | |
95 EpidemicTag (int32_t o = -1) : Tag (), | |
96 m_tag (o) | |
97 { | |
98 } | |
99 | |
100 static TypeId GetTypeId () | |
101 { | |
102 static TypeId tid = TypeId ("ns3::epidemic::EpidemicTag").SetParent<Tag> () | |
103 .SetParent<Tag> () | |
104 .AddConstructor<EpidemicTag> () | |
105 ; | |
106 return tid; | |
107 } | |
108 | |
109 TypeId GetInstanceTypeId () const | |
110 { | |
111 return GetTypeId (); | |
112 } | |
113 | |
114 int32_t GetEpidemicTag () const | |
115 { | |
116 return m_tag; | |
117 } | |
118 | |
119 void SetEpidemicTag (int32_t tag) | |
120 { | |
121 m_tag = tag; | |
122 } | |
123 | |
124 uint32_t GetSerializedSize () const | |
125 { | |
126 return sizeof(int32_t); | |
127 } | |
128 | |
129 void Serialize (TagBuffer i) const | |
130 { | |
131 i.WriteU32 (m_tag); | |
132 } | |
133 | |
134 void Deserialize (TagBuffer i) | |
135 { | |
136 m_tag = i.ReadU32 (); | |
137 } | |
138 | |
139 void Print (std::ostream &os) const | |
140 { | |
141 os << "EpidemicTag: output interface = " << m_tag; | |
142 } | |
143 | |
144 private: | |
145 /// Positive if output device is fixed in RouteOutput | |
146 int32_t m_tag; | |
147 }; | |
148 | |
149 NS_OBJECT_ENSURE_REGISTERED (EpidemicTag); | |
150 | |
151 | |
152 | |
153 RoutingProtocol::RoutingProtocol () | |
154 : m_HopCount (0), | |
155 m_maxQueueLen (0), | |
156 m_queueEntryExpireTime (Seconds (0)), | |
157 m_beaconInterval (Seconds (0)), | |
158 m_dataPacketCounter (0), | |
159 m_queue (m_maxQueueLen,m_queueEntryExpireTime) | |
160 { | |
161 } | |
162 | |
163 RoutingProtocol::~RoutingProtocol () | |
164 { | |
165 } | |
166 | |
167 void RoutingProtocol::DoDispose () | |
168 { | |
169 m_ipv4 = 0; | |
170 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter = m_socketAddr esses.begin (); iter | |
171 != m_socketAddresses.end (); iter++) | |
172 { | |
173 iter->first->Close (); | |
174 } | |
175 m_socketAddresses.clear (); | |
176 Ipv4RoutingProtocol::DoDispose (); | |
177 } | |
178 | |
179 void RoutingProtocol::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const | |
180 { | |
181 /* | |
182 * There is no routing table | |
183 */ | |
184 *stream->GetStream () << "No Routing table "; | |
185 } | |
186 | |
187 | |
188 | |
189 | |
190 void RoutingProtocol::Start () | |
191 { | |
192 NS_LOG_FUNCTION (this ); | |
193 m_queue.SetMaxQueueLen (m_maxQueueLen); | |
194 m_BeaconTimer.SetFunction (&RoutingProtocol::SendBeacons,this); | |
195 m_BeaconTimer.Schedule (m_beaconInterval + MilliSeconds (UniformVariable ().Ge tInteger (0,100))); | |
Tom Henderson
2013/12/08 22:24:26
This will need to be reworked a bit to use Uniform
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
196 } | |
197 | |
198 /* | |
199 a function used to send a packet for a given address | |
200 */ | |
201 | |
202 void RoutingProtocol::SendPacket (Ptr<Packet> p,InetSocketAddress addr) | |
203 { | |
204 NS_LOG_FUNCTION (this << *p); | |
205 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketA ddresses.begin (); j != m_socketAddresses.end (); ++j) | |
206 { | |
207 Ipv4InterfaceAddress iface = j->second; | |
208 if (iface.GetLocal () == m_mainAddress) | |
209 { | |
210 Ptr<Socket> socket = j->first; | |
211 socket->SendTo (p,0, addr); | |
212 } | |
213 } | |
214 NS_LOG_FUNCTION (this << *p); | |
215 } | |
216 | |
217 | |
218 | |
219 void RoutingProtocol::BroadcastPacket (Ptr<Packet> p) | |
220 { | |
221 NS_LOG_FUNCTION (this); | |
222 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketA ddresses.begin (); j != m_socketAddresses.end (); ++j) | |
223 { | |
224 Ptr<Socket> socket = j->first; | |
225 Ipv4InterfaceAddress iface = j->second; | |
226 // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise | |
227 Ipv4Address destination; | |
228 if (iface.GetMask () == Ipv4Mask::GetOnes ()) | |
229 { | |
230 destination = Ipv4Address ("255.255.255.255"); | |
231 } | |
232 else | |
233 { | |
234 destination = iface.GetBroadcast (); | |
235 } | |
236 socket->SendTo (p, 0, InetSocketAddress (destination, EPIDEMIC_PORT)); | |
Tom Henderson
2013/12/08 22:24:26
these kind of Send events ought to be logged. In
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
237 } | |
238 } | |
239 | |
240 | |
241 | |
242 void RoutingProtocol::SendPacketFromQueue (Ipv4Address dst,QueueEntry queueEntry ) | |
243 { | |
244 NS_LOG_FUNCTION (this << "Queue Sending Packet " << dst ); | |
245 Ptr<Packet> p = ConstCast<Packet> (queueEntry.GetPacket ()); | |
246 UnicastForwardCallback ucb = queueEntry.GetUnicastForwardCallback (); | |
247 Ipv4Header header = queueEntry.GetIpv4Header (); | |
248 /* | |
249 * Since Epidemic routing has a control mechanism to drop packets based on ho p count, | |
250 * IP TTL dropping mechanism is avoided by incrementing TTL. | |
Tom Henderson
2013/12/08 22:24:26
Why not just generate a fresh IP header with whate
mjf.alenazi
2013/12/30 23:11:11
I am using the header associated with the packet.
| |
251 */ | |
252 header.SetTtl (header.GetTtl () + 1); | |
253 header.SetPayloadSize (p->GetSize ()); | |
254 Ptr<Ipv4Route> rt = Create<Ipv4Route> (); | |
255 rt->SetSource (header.GetSource ()); | |
256 rt->SetDestination (header.GetDestination ()); | |
257 rt->SetGateway (dst); | |
258 if (m_ipv4->GetInterfaceForAddress (m_mainAddress) != -1) | |
259 { | |
260 Ptr<Node> node = m_ipv4->GetObject<Node> (); | |
261 rt->SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (m_mainAddress))); | |
262 | |
263 } | |
264 | |
265 Ptr<Packet> copy = p->Copy (); | |
266 ucb (rt, copy, header); | |
267 | |
268 } | |
269 | |
270 void RoutingProtocol::SendBeacons () | |
271 { | |
272 NS_LOG_FUNCTION (this << "Broadcasting Beacons"); | |
273 Ptr<Packet> packet = Create<Packet> (); | |
274 EpidemicHeader header; | |
275 header.SetHopCount (m_HopCount); // This number does not have any effect but i t has to be more than 1 to avoid dropping at the receiver | |
276 packet->AddHeader (header); | |
277 TypeHeader tHeader (EPIDEMIC_TYPE_BEACON); | |
278 packet->AddHeader (tHeader); | |
279 EpidemicTag tempTag (1); | |
280 packet->AddPacketTag (tempTag); | |
Tom Henderson
2013/12/08 22:24:26
Is the tag ever removed? Perhaps add a comment he
mjf.alenazi
2013/12/30 23:11:11
Yes, before the packet is delivered
On 2013/12/08
| |
281 Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),&Rou tingProtocol::BroadcastPacket,this, packet); | |
282 m_BeaconTimer.Schedule (m_beaconInterval + MilliSeconds (UniformVariable ().Ge tInteger (0,100))); | |
Tom Henderson
2013/12/08 22:24:26
similar comment here about beacon use of RandomVar
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
283 } | |
284 | |
285 | |
286 uint32_t RoutingProtocol::find_output_device_for_address (Ipv4Address dst) | |
287 { | |
Tom Henderson
2013/12/08 22:24:26
How is this different that Ipv4::GetInterfaceForAd
mjf.alenazi
2013/12/30 23:11:11
My function is trying to match the correct subnet
| |
288 Ptr<Node> mynode = m_ipv4->GetObject<Node> (); | |
289 for (uint32_t i = 0; i < mynode->GetNDevices (); i++) | |
290 { | |
291 Ipv4InterfaceAddress iface = m_ipv4->GetAddress (m_ipv4->GetInterfaceForDe vice (mynode->GetDevice (i)),0); | |
292 if (dst.CombineMask (iface.GetMask ()) == iface.GetLocal ().CombineMask (i face.GetMask ())) | |
293 { | |
294 return i; | |
295 } | |
296 } | |
297 return -1; | |
298 } | |
299 | |
300 | |
301 uint32_t RoutingProtocol::find_loopback_device () | |
302 { | |
303 Ptr<Node> mynode = m_ipv4->GetObject<Node> (); | |
304 for (uint32_t i = 0; i < mynode->GetNDevices (); i++) | |
305 { | |
306 Ipv4InterfaceAddress iface = m_ipv4->GetAddress (m_ipv4->GetInterfaceForDe vice (mynode->GetDevice (i)),0); | |
307 if (iface.GetLocal () == Ipv4Address ("127.0.0.1") ) | |
Tom Henderson
2013/12/08 22:24:26
it may be more robust to check the type of the dev
mjf.alenazi
2013/12/30 23:11:11
Can you help me with this one?
On 2013/12/08 22:2
| |
308 { | |
309 return i; | |
310 } | |
311 } | |
312 return -1; | |
313 } | |
314 | |
315 | |
316 bool RoutingProtocol::IsMyOwnAddress (Ipv4Address src) | |
Tom Henderson
2013/12/08 22:24:26
how is this different from Ipv4::IsDestinationAddr
mjf.alenazi
2013/12/30 23:11:11
I tried pv4::IsDestinationAddress() but it did not
| |
317 { | |
318 NS_LOG_FUNCTION (this << src); | |
319 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = | |
320 m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) | |
321 { | |
322 Ipv4InterfaceAddress iface = j->second; | |
323 if (src == iface.GetLocal ()) | |
324 { | |
325 return true; | |
326 } | |
327 } | |
328 return false; | |
329 } | |
330 | |
331 | |
332 Ptr<Ipv4Route> RoutingProtocol::RouteOutput (Ptr<Packet> p, | |
333 const Ipv4Header &header, | |
334 Ptr<NetDevice> oif, | |
335 Socket::SocketErrno &sockerr) | |
336 { | |
337 | |
338 NS_LOG_FUNCTION (this << "Packet Size" << p->GetSize () << " Packet " << p->G etUid () << " reached node " << m_mainAddress << " sourced from " << header.Get Source () << " going to " << header.GetDestination ()); | |
339 if (IsMyOwnAddress (header.GetDestination ())) | |
340 { | |
341 NS_LOG_LOGIC ("Local delivery a packet" << p->GetUid () << " has arrived d estination " << " At node " << m_mainAddress << " " << header); | |
342 Ptr<Ipv4Route> rt = Create<Ipv4Route> (); | |
343 rt->SetSource (m_mainAddress); | |
344 rt->SetDestination (header.GetDestination ()); | |
345 return rt; | |
346 } | |
347 else | |
348 { | |
349 | |
350 /* | |
351 * Control packets generated at this node, are tagged with EpedemicTag. | |
352 */ | |
353 EpidemicTag tag; | |
354 p->PeekPacketTag (tag); | |
Tom Henderson
2013/12/08 22:24:26
similar comment here-- where is this tag later rem
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
355 Ptr<Ipv4Route> rt = Create<Ipv4Route> (); | |
356 rt->SetSource (m_mainAddress); | |
357 rt->SetDestination (header.GetDestination ()); | |
358 rt->SetGateway (header.GetDestination ()); | |
359 | |
360 if (m_ipv4->GetInterfaceForAddress (m_mainAddress) != -1) | |
361 { | |
362 NS_LOG_DEBUG ( "Returning a route with a destination:" << header.GetDe stination () ); | |
363 | |
364 if ( tag.GetEpidemicTag () != -1) | |
365 { | |
366 /* | |
367 * if the packet is not tagged, it means a data packet | |
368 * Thus, data packet is supposed to be looped back to store it in the epidemic queue. | |
369 */ | |
370 NS_LOG_DEBUG ( "New Data packet looped back"); | |
371 rt->SetOutputDevice (m_ipv4->GetNetDevice (find_loopback_device () )); | |
372 } | |
373 else | |
374 { | |
375 /* | |
376 * if the packet is tagged, it is an Epidemic control packet | |
377 * Thus, find the corresponding output device | |
378 */ | |
379 NS_LOG_DEBUG ( "Epidemic triggered packets :" << header.GetDestina tion () << " found " << find_output_device_for_address (header.GetDestination ())); | |
380 rt->SetOutputDevice (m_ipv4->GetNetDevice (find_output_device_for_ address (header.GetDestination ()))); | |
381 } | |
382 } | |
383 return rt; | |
384 } | |
385 | |
386 } | |
387 | |
388 | |
389 bool RoutingProtocol::RouteInput (Ptr<const Packet> p, | |
390 const Ipv4Header &header, | |
391 Ptr<const NetDevice> idev, | |
392 UnicastForwardCallback ucb, | |
393 MulticastForwardCallback mcb, | |
394 LocalDeliverCallback lcb, | |
395 ErrorCallback ecb) | |
396 { | |
397 NS_LOG_FUNCTION (this << header << *p ); | |
398 NS_ASSERT (m_ipv4 != 0); | |
399 NS_ASSERT (p != 0); | |
400 // Check if input device supports IP | |
401 NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0); | |
402 /* | |
403 If there are no interfaces, ignore the packet and return false | |
404 */ | |
405 if (m_socketAddresses.empty ()) | |
406 { | |
407 NS_LOG_ERROR ("No interfaces"); | |
408 return false; | |
409 } | |
410 | |
411 | |
412 if (header.GetTtl () < 1) | |
413 { | |
414 NS_LOG_DEBUG ("TTL expired, Packet is dropped " << p->GetUid ()); | |
415 return false; | |
416 } | |
417 | |
418 | |
419 if (header.GetProtocol () == 1) | |
420 { | |
421 NS_LOG_DEBUG ("Does not deliver ICMP packets " << p->GetUid ()); | |
422 return false; | |
423 } | |
424 | |
425 /* | |
426 * Check all the interfaces local addresses for local delivery | |
427 */ | |
428 | |
429 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = | |
430 m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) | |
431 { | |
432 Ipv4InterfaceAddress iface = j->second; | |
433 int32_t iif = m_ipv4->GetInterfaceForDevice (idev); | |
434 if (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()) == iif) | |
435 { | |
436 if (header.GetDestination () == iface.GetBroadcast () || header.GetDes tination () == m_mainAddress ) | |
437 { | |
438 EpidemicTag tag; | |
439 p->PeekPacketTag (tag); | |
440 EpidemicHeader epidemicHeader; | |
441 Ptr<Packet> local_copy = p->Copy (); | |
442 /* | |
443 * If this is a data packet, add it to the epidemic queue in order to avoid | |
444 * receiving duplicates of the same packet. | |
445 */ | |
446 if (tag.GetEpidemicTag () < 1) | |
447 { | |
448 Ptr<Packet> copy = p->Copy (); | |
449 QueueEntry newEntry (copy, header, ucb, ecb); | |
450 EpidemicHeader current_epidemicHeader; | |
451 copy->PeekHeader (current_epidemicHeader); | |
452 newEntry.SetExpireTime (m_queueEntryExpireTime + current_epide micHeader.GetTimeStamp ()); | |
453 newEntry.SetPacketID (current_epidemicHeader.GetPacketID ()); | |
454 m_queue.Enqueue (newEntry); | |
455 // Remove the packet header for delivery | |
456 EpidemicHeader epidemicHeader; | |
457 local_copy->RemoveHeader (epidemicHeader); | |
458 } | |
459 /* | |
460 Deliver the packet locally | |
461 */ | |
462 | |
463 lcb (local_copy, header, iif); | |
464 return true; | |
465 | |
466 } | |
467 } | |
468 } | |
469 | |
470 | |
471 | |
472 /* | |
473 If the packet does not have an epidemic header, create one and attach it to th e packet. | |
474 This condition is called one the packet is originated locally and does not hav e an epidemic header | |
475 */ | |
476 | |
477 Ptr<Packet> copy = p->Copy (); | |
478 NS_LOG_LOGIC ("Creating Epidemic packet " << p->GetUid () << " Src " << head er.GetSource () << " Dest " << header.GetDestination () << " Size before" << c opy->GetSize ()); | |
479 /* | |
480 * The global packet id format: 32 bit(Source IP):32bit(source packet counter) | |
481 */ | |
482 m_dataPacketCounter++; | |
483 uint64_t global_packet_ID = header.GetSource ().Get (); | |
484 global_packet_ID = global_packet_ID << 32 | m_dataPacketCounter; | |
485 | |
486 | |
487 | |
488 | |
489 | |
490 //ADD EPIDEMIC HEADER | |
Tom Henderson
2013/12/08 22:24:26
this kind of comment might be better to add as a d
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
491 EpidemicHeader new_epidemicHeader; | |
492 new_epidemicHeader.SetPacketID (global_packet_ID); | |
493 new_epidemicHeader.SetTimeStamp (Simulator::Now ()); | |
494 new_epidemicHeader.SetHopCount (m_HopCount); | |
495 | |
496 // Adding the data packet to the queue | |
497 QueueEntry newEntry (copy, header, ucb, ecb); | |
498 newEntry.SetPacketID (global_packet_ID); | |
499 | |
500 if (IsMyOwnAddress (header.GetSource ())) | |
501 { | |
502 // If the packet is generated in this node, add the epidemic header | |
503 copy->AddHeader (new_epidemicHeader); | |
504 // If the packet is generated in this node, make the Expire time start fro m now + the user specified period | |
505 newEntry.SetExpireTime (m_queueEntryExpireTime + Simulator::Now ()); | |
506 | |
507 } | |
508 else | |
509 { | |
510 // If the packet is generated in another node, read the epidemic header | |
511 EpidemicHeader current_epidemicHeader; | |
512 copy->RemoveHeader (current_epidemicHeader); | |
513 if (current_epidemicHeader.GetHopCount () <= 1 || (current_epidemicHeader. GetTimeStamp () + m_queueEntryExpireTime) < Simulator::Now () ) | |
514 { | |
515 // Exit the function to not add the packet to the queue since the flo od count limit is reached | |
Tom Henderson
2013/12/08 22:24:26
code like this would benefit from logging statemen
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
516 return true; | |
517 } | |
518 // If the packet is generated in another node, use the timestamp from the epidemic header | |
519 newEntry.SetExpireTime (m_queueEntryExpireTime + current_epidemicHeader.Ge tTimeStamp ()); | |
520 // If the packet is generated in another node, use the PacketID from the e pidemic header | |
521 newEntry.SetPacketID (current_epidemicHeader.GetPacketID ()); | |
522 //Decrease the packet flood counter | |
523 current_epidemicHeader.SetHopCount (current_epidemicHeader.GetHopCount () - 1); | |
524 // Add the updated header | |
525 copy->AddHeader (current_epidemicHeader); | |
526 } | |
527 | |
528 m_queue.Enqueue (newEntry); | |
529 return true; | |
530 | |
531 } | |
532 | |
533 void RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4) | |
534 { | |
535 NS_LOG_FUNCTION (this); | |
536 m_ipv4 = ipv4; | |
537 Simulator::ScheduleNow (&RoutingProtocol::Start,this); | |
538 } | |
539 | |
540 void RoutingProtocol::NotifyInterfaceUp (uint32_t i) | |
541 { | |
542 NS_LOG_FUNCTION (this << i); | |
543 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
544 Ipv4InterfaceAddress iface = l3->GetAddress (i,0); | |
545 if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) | |
546 { | |
547 return; | |
548 } | |
549 if (m_mainAddress == Ipv4Address ()) | |
550 { | |
551 m_mainAddress = iface.GetLocal (); | |
552 } | |
553 | |
554 /* | |
555 Create a socket to be used for epidemic routing port | |
556 */ | |
557 TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); | |
558 Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),tid); | |
559 socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvEpidemic,this)); | |
560 socket->BindToNetDevice (l3->GetNetDevice (i)); | |
561 socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), EPIDEMIC_PORT)); | |
562 socket->SetAllowBroadcast (true); | |
563 m_socketAddresses.insert (std::make_pair (socket,iface)); | |
564 } | |
565 | |
566 void RoutingProtocol::NotifyInterfaceDown (uint32_t i) | |
567 { | |
568 NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ()); | |
569 // Disable layer 2 link state monitoring (if possible) | |
570 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
571 Ptr<NetDevice> dev = l3->GetNetDevice (i); | |
572 // Close socket | |
573 Ptr<Socket> socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0) ); | |
574 NS_ASSERT (socket); | |
575 socket->Close (); | |
576 m_socketAddresses.erase (socket); | |
577 } | |
578 | |
579 void RoutingProtocol::NotifyAddAddress (uint32_t i,Ipv4InterfaceAddress address) | |
580 { | |
581 NS_LOG_FUNCTION (this << " interface " << i << " address " << address); | |
582 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
583 if (!l3->IsUp (i)) | |
584 { | |
585 return; | |
586 } | |
587 if (l3->GetNAddresses (i) == 1) | |
588 { | |
589 Ipv4InterfaceAddress iface = l3->GetAddress (i, 0); | |
590 Ptr<Socket> socket = FindSocketWithInterfaceAddress (iface); | |
591 if (!socket) | |
592 { | |
593 if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) | |
594 { | |
595 return; | |
596 } | |
597 // Create a socket to listen only on this interface | |
598 Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), | |
599 UdpSocketFactory::GetTypeId ()); | |
600 NS_ASSERT (socket != 0); | |
601 socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvEpidemic, this)); | |
602 socket->BindToNetDevice (l3->GetNetDevice (i)); | |
603 socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), EPIDEMIC_PORT )); | |
604 socket->SetAllowBroadcast (true); | |
605 m_socketAddresses.insert (std::make_pair (socket, iface)); | |
606 } | |
607 } | |
608 else | |
609 { | |
610 NS_LOG_LOGIC ("Epidemic does not work with more then one address per each interface. Ignore added address"); | |
Tom Henderson
2013/12/08 22:24:26
state this restriction in the documentation (class
mjf.alenazi
2013/12/30 23:11:11
Done.
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
611 } | |
612 | |
613 | |
614 | |
615 } | |
616 | |
617 void RoutingProtocol::NotifyRemoveAddress (uint32_t i,Ipv4InterfaceAddress addre ss) | |
618 { | |
619 | |
620 NS_LOG_FUNCTION (this); | |
621 Ptr<Socket> socket = FindSocketWithInterfaceAddress (address); | |
622 if (socket) | |
623 { | |
624 m_socketAddresses.erase (socket); | |
625 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
626 if (l3->GetNAddresses (i)) | |
627 { | |
628 Ipv4InterfaceAddress iface = l3->GetAddress (i, 0); | |
629 // Create a socket to listen only on this interface | |
630 Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), | |
631 UdpSocketFactory::GetTypeId ()); | |
632 NS_ASSERT (socket != 0); | |
633 socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvEpidemic, this)); | |
634 // Bind to any IP address so that broadcasts can be received | |
635 socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), EPIDEMIC_PORT )); | |
636 socket->SetAllowBroadcast (true); | |
637 m_socketAddresses.insert (std::make_pair (socket, iface)); | |
638 | |
639 } | |
640 | |
641 } | |
642 else | |
643 { | |
644 NS_LOG_LOGIC ("Remove address not participating in Epidemic operation"); | |
645 } | |
646 } | |
647 | |
648 | |
649 | |
650 void RoutingProtocol::SendDisjointPackets (std::vector<uint64_t> list,Ipv4Addres s dest) | |
651 { | |
652 NS_LOG_FUNCTION (this << " send to " << dest); | |
653 /* | |
654 This function is used to find send the packets listed in the vector list | |
655 */ | |
656 for (std::vector<uint64_t>::iterator i = list.begin (); i != list.end (); ++i) | |
657 { | |
658 QueueEntry newEntry = m_queue.Find (*i); | |
659 if (newEntry.GetPacket ()) | |
660 { | |
661 Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,10 0)),&RoutingProtocol::SendPacketFromQueue,this,dest, newEntry); | |
Tom Henderson
2013/12/08 22:24:26
this is another usage of UniformVariable that must
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
662 } | |
663 } | |
664 } | |
665 | |
666 | |
667 | |
668 Ptr<Socket> | |
669 RoutingProtocol::FindSocketWithInterfaceAddress (Ipv4InterfaceAddress addr ) con st | |
670 { | |
671 NS_LOG_FUNCTION (this << addr); | |
672 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = | |
673 m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) | |
674 { | |
675 Ptr<Socket> socket = j->first; | |
676 Ipv4InterfaceAddress iface = j->second; | |
677 if (iface == addr) | |
678 { | |
679 return socket; | |
680 } | |
681 } | |
682 Ptr<Socket> socket; | |
683 return socket; | |
684 } | |
685 | |
686 | |
687 void RoutingProtocol::SendSummaryVector (Ipv4Address dest,bool firstNode) | |
688 { | |
689 NS_LOG_FUNCTION (this << " sent to " << dest); | |
690 // Creating the packet | |
691 Ptr<Packet> packet_summary = Create<Packet> (); | |
692 EpidemicSummaryVectorHeader header_summary (m_queue.GetSummaryVector ()); | |
693 TypeHeader tHeader; | |
694 if (firstNode) | |
695 { | |
696 tHeader.SetInstanceTypeId (EPIDEMIC_TYPE_REPLY); | |
697 } | |
698 else | |
699 { | |
700 tHeader.SetInstanceTypeId (EPIDEMIC_TYPE_REPLY_BACK); | |
701 } | |
702 packet_summary->AddHeader (header_summary); | |
703 EpidemicTag tempTag (1); | |
704 packet_summary->AddHeader (tHeader); | |
705 packet_summary->AddPacketTag (tempTag); | |
706 // Send the summary vector | |
707 NS_LOG_DEBUG ("Sending the summary vector 2 packet " << packet_summary->GetUid () << " to " << dest ); | |
708 InetSocketAddress addr = InetSocketAddress (dest, EPIDEMIC_PORT); | |
709 Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),&Rou tingProtocol::SendPacket,this, packet_summary, addr); | |
Tom Henderson
2013/12/08 22:24:26
another instance of jitter that should be refactor
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
710 | |
711 } | |
712 | |
713 | |
714 | |
715 void RoutingProtocol::RecvEpidemic (Ptr<Socket> socket) | |
716 { | |
717 m_queue.DropExpiredPackets (); | |
718 NS_LOG_FUNCTION (this << socket); | |
Tom Henderson
2013/12/08 22:24:26
NS_LOG_FUNCTION should be the first statement
mjf.alenazi
2013/12/30 23:11:11
Done.
mjf.alenazi
2013/12/30 23:11:11
Done.
| |
719 Address address; | |
720 Ptr<Packet> packet = socket->RecvFrom (address); | |
721 TypeHeader tHeader (EPIDEMIC_TYPE_BEACON); | |
722 packet->RemoveHeader (tHeader); | |
723 | |
724 InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (address); | |
725 Ipv4Address sender = inetSourceAddr.GetIpv4 (); | |
726 Ptr<Packet> packet_copy = packet->Copy (); | |
727 if (tHeader.Get () == EPIDEMIC_TYPE_BEACON) | |
728 { | |
729 NS_LOG_LOGIC ("Got a beacon from " << sender << " " << packet->GetUid () < < " " << m_mainAddress); | |
730 // Anti-entropy session | |
731 // Check if you have the smaller address | |
732 if (m_mainAddress.Get () < sender.Get ()) | |
733 { | |
734 SendSummaryVector (sender,true); | |
735 } | |
736 } | |
737 else if (tHeader.Get () == EPIDEMIC_TYPE_REPLY) | |
738 { | |
739 NS_LOG_LOGIC ("Got a A reply from " << sender << " " << packet->GetUid () << " " << m_mainAddress); | |
740 EpidemicSummaryVectorHeader packet_SMV; | |
741 packet->RemoveHeader (packet_SMV); | |
742 std::vector<uint64_t> sm_vec = packet_SMV.GetSummaryVector (); | |
743 SendDisjointPackets (m_queue.FindDisjointPackets (sm_vec),sender); | |
744 SendSummaryVector (sender,false); | |
745 } | |
746 else if (tHeader.Get () == EPIDEMIC_TYPE_REPLY_BACK) | |
747 { | |
748 NS_LOG_LOGIC ("Got a A reply back from " << sender << " " << packet->GetUi d () << " " << m_mainAddress); | |
749 EpidemicSummaryVectorHeader packet_SMV; | |
750 packet->RemoveHeader (packet_SMV); | |
751 std::vector<uint64_t> sm_vec = packet_SMV.GetSummaryVector (); | |
752 SendDisjointPackets (m_queue.FindDisjointPackets (sm_vec),sender); | |
753 | |
754 } | |
755 } | |
756 } //end namespace epidemic | |
757 } //end namespace ns3 | |
OLD | NEW |