1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2007 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 |
|
21 #include "ns3/log.h" |
|
22 #include "ns3/node.h" |
|
23 #include "ns3/inet-socket-address.h" |
|
24 #include "ns3/ipv4-route.h" |
|
25 #include "ns3/ipv4.h" |
|
26 #include "ns3/udp-socket-factory.h" |
|
27 #include "ns3/trace-source-accessor.h" |
|
28 #include "ns3/uinteger.h" |
|
29 #include "ns3/boolean.h" |
|
30 #include "udp-socket-impl.h" |
|
31 #include "udp-l4-protocol.h" |
|
32 #include "ipv4-end-point.h" |
|
33 #include "ipv4-l4-demux.h" |
|
34 |
|
35 NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl"); |
|
36 |
|
37 namespace ns3 { |
|
38 |
|
39 static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507; |
|
40 |
|
41 // Add attributes generic to all UdpSockets to base class UdpSocket |
|
42 TypeId |
|
43 UdpSocketImpl::GetTypeId (void) |
|
44 { |
|
45 static TypeId tid = TypeId ("ns3::UdpSocketImpl") |
|
46 .SetParent<UdpSocket> () |
|
47 .AddConstructor<UdpSocketImpl> () |
|
48 .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow", |
|
49 MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace)) |
|
50 ; |
|
51 return tid; |
|
52 } |
|
53 |
|
54 UdpSocketImpl::UdpSocketImpl () |
|
55 : m_endPoint (0), |
|
56 m_node (0), |
|
57 m_udp (0), |
|
58 m_errno (ERROR_NOTERROR), |
|
59 m_shutdownSend (false), |
|
60 m_shutdownRecv (false), |
|
61 m_connected (false), |
|
62 m_rxAvailable (0) |
|
63 { |
|
64 NS_LOG_FUNCTION_NOARGS (); |
|
65 } |
|
66 |
|
67 UdpSocketImpl::~UdpSocketImpl () |
|
68 { |
|
69 NS_LOG_FUNCTION_NOARGS (); |
|
70 |
|
71 m_node = 0; |
|
72 if (m_endPoint != 0) |
|
73 { |
|
74 NS_ASSERT (m_udp != 0); |
|
75 /** |
|
76 * Note that this piece of code is a bit tricky: |
|
77 * when DeAllocate is called, it will call into |
|
78 * Ipv4EndPointDemux::Deallocate which triggers |
|
79 * a delete of the associated endPoint which triggers |
|
80 * in turn a call to the method ::Destroy below |
|
81 * will will zero the m_endPoint field. |
|
82 */ |
|
83 NS_ASSERT (m_endPoint != 0); |
|
84 m_udp->DeAllocate (m_endPoint); |
|
85 NS_ASSERT (m_endPoint == 0); |
|
86 } |
|
87 m_udp = 0; |
|
88 } |
|
89 |
|
90 void |
|
91 UdpSocketImpl::SetNode (Ptr<Node> node) |
|
92 { |
|
93 NS_LOG_FUNCTION_NOARGS (); |
|
94 m_node = node; |
|
95 |
|
96 } |
|
97 void |
|
98 UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp) |
|
99 { |
|
100 NS_LOG_FUNCTION_NOARGS (); |
|
101 m_udp = udp; |
|
102 } |
|
103 |
|
104 |
|
105 enum Socket::SocketErrno |
|
106 UdpSocketImpl::GetErrno (void) const |
|
107 { |
|
108 NS_LOG_FUNCTION_NOARGS (); |
|
109 return m_errno; |
|
110 } |
|
111 |
|
112 Ptr<Node> |
|
113 UdpSocketImpl::GetNode (void) const |
|
114 { |
|
115 NS_LOG_FUNCTION_NOARGS (); |
|
116 return m_node; |
|
117 } |
|
118 |
|
119 void |
|
120 UdpSocketImpl::Destroy (void) |
|
121 { |
|
122 NS_LOG_FUNCTION_NOARGS (); |
|
123 m_node = 0; |
|
124 m_endPoint = 0; |
|
125 m_udp = 0; |
|
126 } |
|
127 |
|
128 int |
|
129 UdpSocketImpl::FinishBind (void) |
|
130 { |
|
131 NS_LOG_FUNCTION_NOARGS (); |
|
132 if (m_endPoint == 0) |
|
133 { |
|
134 return -1; |
|
135 } |
|
136 m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this))); |
|
137 m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this))); |
|
138 return 0; |
|
139 } |
|
140 |
|
141 int |
|
142 UdpSocketImpl::Bind (void) |
|
143 { |
|
144 NS_LOG_FUNCTION_NOARGS (); |
|
145 m_endPoint = m_udp->Allocate (); |
|
146 return FinishBind (); |
|
147 } |
|
148 |
|
149 int |
|
150 UdpSocketImpl::Bind (const Address &address) |
|
151 { |
|
152 NS_LOG_FUNCTION (this << address); |
|
153 |
|
154 if (!InetSocketAddress::IsMatchingType (address)) |
|
155 { |
|
156 NS_LOG_ERROR ("Not IsMatchingType"); |
|
157 return ERROR_INVAL; |
|
158 } |
|
159 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
|
160 Ipv4Address ipv4 = transport.GetIpv4 (); |
|
161 uint16_t port = transport.GetPort (); |
|
162 if (ipv4 == Ipv4Address::GetAny () && port == 0) |
|
163 { |
|
164 m_endPoint = m_udp->Allocate (); |
|
165 } |
|
166 else if (ipv4 == Ipv4Address::GetAny () && port != 0) |
|
167 { |
|
168 m_endPoint = m_udp->Allocate (port); |
|
169 } |
|
170 else if (ipv4 != Ipv4Address::GetAny () && port == 0) |
|
171 { |
|
172 m_endPoint = m_udp->Allocate (ipv4); |
|
173 } |
|
174 else if (ipv4 != Ipv4Address::GetAny () && port != 0) |
|
175 { |
|
176 m_endPoint = m_udp->Allocate (ipv4, port); |
|
177 } |
|
178 |
|
179 return FinishBind (); |
|
180 } |
|
181 |
|
182 int |
|
183 UdpSocketImpl::ShutdownSend (void) |
|
184 { |
|
185 NS_LOG_FUNCTION_NOARGS (); |
|
186 m_shutdownSend = true; |
|
187 return 0; |
|
188 } |
|
189 |
|
190 int |
|
191 UdpSocketImpl::ShutdownRecv (void) |
|
192 { |
|
193 NS_LOG_FUNCTION_NOARGS (); |
|
194 m_shutdownRecv = false; |
|
195 return 0; |
|
196 } |
|
197 |
|
198 int |
|
199 UdpSocketImpl::Close(void) |
|
200 { |
|
201 NS_LOG_FUNCTION_NOARGS (); |
|
202 NotifyCloseCompleted (); |
|
203 return 0; |
|
204 } |
|
205 |
|
206 int |
|
207 UdpSocketImpl::Connect(const Address & address) |
|
208 { |
|
209 NS_LOG_FUNCTION (this << address); |
|
210 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
|
211 m_defaultAddress = transport.GetIpv4 (); |
|
212 m_defaultPort = transport.GetPort (); |
|
213 NotifyConnectionSucceeded (); |
|
214 m_connected = true; |
|
215 |
|
216 return 0; |
|
217 } |
|
218 |
|
219 int |
|
220 UdpSocketImpl::Listen (uint32_t queueLimit) |
|
221 { |
|
222 m_errno = Socket::ERROR_OPNOTSUPP; |
|
223 return -1; |
|
224 } |
|
225 |
|
226 int |
|
227 UdpSocketImpl::Send (Ptr<Packet> p) |
|
228 { |
|
229 NS_LOG_FUNCTION (this << p); |
|
230 |
|
231 if (!m_connected) |
|
232 { |
|
233 m_errno = ERROR_NOTCONN; |
|
234 return -1; |
|
235 } |
|
236 return DoSend (p); |
|
237 } |
|
238 |
|
239 int |
|
240 UdpSocketImpl::DoSend (Ptr<Packet> p) |
|
241 { |
|
242 NS_LOG_FUNCTION_NOARGS (); |
|
243 if (m_endPoint == 0) |
|
244 { |
|
245 if (Bind () == -1) |
|
246 { |
|
247 NS_ASSERT (m_endPoint == 0); |
|
248 return -1; |
|
249 } |
|
250 NS_ASSERT (m_endPoint != 0); |
|
251 } |
|
252 if (m_shutdownSend) |
|
253 { |
|
254 m_errno = ERROR_SHUTDOWN; |
|
255 return -1; |
|
256 } |
|
257 |
|
258 return DoSendTo (p, m_defaultAddress, m_defaultPort); |
|
259 } |
|
260 |
|
261 int |
|
262 UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address) |
|
263 { |
|
264 NS_LOG_FUNCTION (this << p << address); |
|
265 |
|
266 if (!m_connected) |
|
267 { |
|
268 NS_LOG_LOGIC ("Not connected"); |
|
269 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
|
270 Ipv4Address ipv4 = transport.GetIpv4 (); |
|
271 uint16_t port = transport.GetPort (); |
|
272 return DoSendTo (p, ipv4, port); |
|
273 } |
|
274 else |
|
275 { |
|
276 // connected UDP socket must use default addresses |
|
277 NS_LOG_LOGIC ("Connected"); |
|
278 return DoSendTo (p, m_defaultAddress, m_defaultPort); |
|
279 } |
|
280 } |
|
281 |
|
282 int |
|
283 UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port) |
|
284 { |
|
285 NS_LOG_FUNCTION (this << p << dest << port); |
|
286 |
|
287 if (m_endPoint == 0) |
|
288 { |
|
289 if (Bind () == -1) |
|
290 { |
|
291 NS_ASSERT (m_endPoint == 0); |
|
292 return -1; |
|
293 } |
|
294 NS_ASSERT (m_endPoint != 0); |
|
295 } |
|
296 if (m_shutdownSend) |
|
297 { |
|
298 m_errno = ERROR_SHUTDOWN; |
|
299 return -1; |
|
300 } |
|
301 |
|
302 if (p->GetSize () > GetTxAvailable () ) |
|
303 { |
|
304 m_errno = ERROR_MSGSIZE; |
|
305 return -1; |
|
306 } |
|
307 |
|
308 uint32_t localIfIndex; |
|
309 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> (); |
|
310 |
|
311 // Locally override the IP TTL for this socket |
|
312 // We cannot directly modify the TTL at this stage, so we set a Packet tag |
|
313 // The destination can be either multicast, unicast/anycast, or |
|
314 // either all-hosts broadcast or limited (subnet-directed) broadcast. |
|
315 // For the latter two broadcast types, the TTL will later be set to one |
|
316 // irrespective of what is set in these socket options. So, this tagging |
|
317 // may end up setting the TTL of a limited broadcast packet to be |
|
318 // the same as a unicast, but it will be fixed further down the stack |
|
319 //NS_LOG_UNCOND ("IPttl: " << m_ipTtl); |
|
320 if (m_ipMulticastTtl != 0 && dest.IsMulticast ()) |
|
321 { |
|
322 SocketIpTtlTag tag; |
|
323 tag.SetTtl (m_ipMulticastTtl); |
|
324 p->AddTag (tag); |
|
325 } |
|
326 else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ()) |
|
327 { |
|
328 SocketIpTtlTag tag; |
|
329 tag.SetTtl (m_ipTtl); |
|
330 p->AddTag (tag); |
|
331 } |
|
332 // |
|
333 // If dest is sent to the limited broadcast address (all ones), |
|
334 // convert it to send a copy of the packet out of every interface |
|
335 // |
|
336 if (dest.IsBroadcast ()) |
|
337 { |
|
338 NS_LOG_LOGIC ("Limited broadcast start."); |
|
339 for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ ) |
|
340 { |
|
341 Ipv4Address addri = ipv4->GetAddress (i); |
|
342 Ipv4Mask maski = ipv4->GetNetworkMask (i); |
|
343 Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski); |
|
344 NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast |
|
345 << " (mask is " << maski << ")"); |
|
346 m_udp->Send (p->Copy (), addri, bcast, |
|
347 m_endPoint->GetLocalPort (), port); |
|
348 NotifyDataSent (p->GetSize ()); |
|
349 } |
|
350 NS_LOG_LOGIC ("Limited broadcast end."); |
|
351 return p->GetSize(); |
|
352 } |
|
353 else if (ipv4->GetIfIndexForDestination(dest, localIfIndex)) |
|
354 { |
|
355 NS_LOG_LOGIC ("Route exists"); |
|
356 m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest, |
|
357 m_endPoint->GetLocalPort (), port); |
|
358 NotifyDataSent (p->GetSize ()); |
|
359 return p->GetSize();; |
|
360 } |
|
361 else |
|
362 { |
|
363 NS_LOG_ERROR ("ERROR_NOROUTETOHOST"); |
|
364 m_errno = ERROR_NOROUTETOHOST; |
|
365 return -1; |
|
366 } |
|
367 |
|
368 return 0; |
|
369 } |
|
370 |
|
371 // XXX maximum message size for UDP broadcast is limited by MTU |
|
372 // size of underlying link; we are not checking that now. |
|
373 uint32_t |
|
374 UdpSocketImpl::GetTxAvailable (void) const |
|
375 { |
|
376 NS_LOG_FUNCTION_NOARGS (); |
|
377 // No finite send buffer is modelled, but we must respect |
|
378 // the maximum size of an IP datagram (65535 bytes - headers). |
|
379 return MAX_IPV4_UDP_DATAGRAM_SIZE; |
|
380 } |
|
381 |
|
382 int |
|
383 UdpSocketImpl::SendTo (Ptr<Packet> p, const Address &address) |
|
384 { |
|
385 NS_LOG_FUNCTION (this << address << p); |
|
386 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
|
387 Ipv4Address ipv4 = transport.GetIpv4 (); |
|
388 uint16_t port = transport.GetPort (); |
|
389 return DoSendTo (p, ipv4, port); |
|
390 } |
|
391 |
|
392 Ptr<Packet> |
|
393 UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) |
|
394 { |
|
395 NS_LOG_FUNCTION_NOARGS (); |
|
396 if (m_deliveryQueue.empty() ) |
|
397 { |
|
398 return 0; |
|
399 } |
|
400 Ptr<Packet> p = m_deliveryQueue.front (); |
|
401 if (p->GetSize () <= maxSize) |
|
402 { |
|
403 m_deliveryQueue.pop (); |
|
404 m_rxAvailable -= p->GetSize (); |
|
405 } |
|
406 else |
|
407 { |
|
408 p = 0; |
|
409 } |
|
410 return p; |
|
411 } |
|
412 |
|
413 uint32_t |
|
414 UdpSocketImpl::GetRxAvailable (void) const |
|
415 { |
|
416 NS_LOG_FUNCTION_NOARGS (); |
|
417 // We separately maintain this state to avoid walking the queue |
|
418 // every time this might be called |
|
419 return m_rxAvailable; |
|
420 } |
|
421 |
|
422 void |
|
423 UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port) |
|
424 { |
|
425 NS_LOG_FUNCTION (this << packet << ipv4 << port); |
|
426 |
|
427 if (m_shutdownRecv) |
|
428 { |
|
429 return; |
|
430 } |
|
431 if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize) |
|
432 { |
|
433 Address address = InetSocketAddress (ipv4, port); |
|
434 SocketRxAddressTag tag; |
|
435 tag.SetAddress (address); |
|
436 packet->AddTag (tag); |
|
437 m_deliveryQueue.push (packet); |
|
438 m_rxAvailable += packet->GetSize (); |
|
439 NotifyDataRecv (); |
|
440 } |
|
441 else |
|
442 { |
|
443 // In general, this case should not occur unless the |
|
444 // receiving application reads data from this socket slowly |
|
445 // in comparison to the arrival rate |
|
446 // |
|
447 // drop and trace packet |
|
448 NS_LOG_WARN ("No receive buffer space available. Drop."); |
|
449 m_dropTrace (packet); |
|
450 } |
|
451 } |
|
452 |
|
453 |
|
454 void |
|
455 UdpSocketImpl::SetRcvBufSize (uint32_t size) |
|
456 { |
|
457 m_rcvBufSize = size; |
|
458 } |
|
459 |
|
460 uint32_t |
|
461 UdpSocketImpl::GetRcvBufSize (void) const |
|
462 { |
|
463 return m_rcvBufSize; |
|
464 } |
|
465 |
|
466 void |
|
467 UdpSocketImpl::SetIpTtl (uint32_t ipTtl) |
|
468 { |
|
469 m_ipTtl = ipTtl; |
|
470 } |
|
471 |
|
472 uint32_t |
|
473 UdpSocketImpl::GetIpTtl (void) const |
|
474 { |
|
475 return m_ipTtl; |
|
476 } |
|
477 |
|
478 void |
|
479 UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl) |
|
480 { |
|
481 m_ipMulticastTtl = ipTtl; |
|
482 } |
|
483 |
|
484 uint32_t |
|
485 UdpSocketImpl::GetIpMulticastTtl (void) const |
|
486 { |
|
487 return m_ipMulticastTtl; |
|
488 } |
|
489 |
|
490 } //namespace ns3 |
|
491 |
|
492 |
|
493 #ifdef RUN_SELF_TESTS |
|
494 |
|
495 #include "ns3/test.h" |
|
496 #include "ns3/socket-factory.h" |
|
497 #include "ns3/udp-socket-factory.h" |
|
498 #include "ns3/simulator.h" |
|
499 #include "ns3/simple-channel.h" |
|
500 #include "ns3/simple-net-device.h" |
|
501 #include "ns3/drop-tail-queue.h" |
|
502 #include "internet-stack.h" |
|
503 #include <string> |
|
504 |
|
505 namespace ns3 { |
|
506 |
|
507 class UdpSocketImplTest: public Test |
|
508 { |
|
509 Ptr<Packet> m_receivedPacket; |
|
510 Ptr<Packet> m_receivedPacket2; |
|
511 |
|
512 public: |
|
513 virtual bool RunTests (void); |
|
514 UdpSocketImplTest (); |
|
515 |
|
516 void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from); |
|
517 void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from); |
|
518 void ReceivePkt (Ptr<Socket> socket); |
|
519 void ReceivePkt2 (Ptr<Socket> socket); |
|
520 }; |
|
521 |
|
522 |
|
523 UdpSocketImplTest::UdpSocketImplTest () |
|
524 : Test ("UdpSocketImpl") |
|
525 { |
|
526 } |
|
527 |
|
528 void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from) |
|
529 { |
|
530 m_receivedPacket = packet; |
|
531 } |
|
532 |
|
533 void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from) |
|
534 { |
|
535 m_receivedPacket2 = packet; |
|
536 } |
|
537 |
|
538 void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket) |
|
539 { |
|
540 uint32_t availableData; |
|
541 availableData = socket->GetRxAvailable (); |
|
542 m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0); |
|
543 NS_ASSERT (availableData == m_receivedPacket->GetSize ()); |
|
544 } |
|
545 |
|
546 void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket) |
|
547 { |
|
548 uint32_t availableData; |
|
549 availableData = socket->GetRxAvailable (); |
|
550 m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0); |
|
551 NS_ASSERT (availableData == m_receivedPacket2->GetSize ()); |
|
552 } |
|
553 |
|
554 bool |
|
555 UdpSocketImplTest::RunTests (void) |
|
556 { |
|
557 bool result = true; |
|
558 |
|
559 // Create topology |
|
560 |
|
561 // Receiver Node |
|
562 Ptr<Node> rxNode = CreateObject<Node> (); |
|
563 AddInternetStack (rxNode); |
|
564 Ptr<SimpleNetDevice> rxDev1, rxDev2; |
|
565 { // first interface |
|
566 rxDev1 = CreateObject<SimpleNetDevice> (); |
|
567 rxDev1->SetAddress (Mac48Address::Allocate ()); |
|
568 rxNode->AddDevice (rxDev1); |
|
569 Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> (); |
|
570 uint32_t netdev_idx = ipv4->AddInterface (rxDev1); |
|
571 ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1")); |
|
572 ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); |
|
573 ipv4->SetUp (netdev_idx); |
|
574 } |
|
575 |
|
576 { // second interface |
|
577 rxDev2 = CreateObject<SimpleNetDevice> (); |
|
578 rxDev2->SetAddress (Mac48Address::Allocate ()); |
|
579 rxNode->AddDevice (rxDev2); |
|
580 Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> (); |
|
581 uint32_t netdev_idx = ipv4->AddInterface (rxDev2); |
|
582 ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1")); |
|
583 ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); |
|
584 ipv4->SetUp (netdev_idx); |
|
585 } |
|
586 |
|
587 // Sender Node |
|
588 Ptr<Node> txNode = CreateObject<Node> (); |
|
589 AddInternetStack (txNode); |
|
590 Ptr<SimpleNetDevice> txDev1; |
|
591 { |
|
592 txDev1 = CreateObject<SimpleNetDevice> (); |
|
593 txDev1->SetAddress (Mac48Address::Allocate ()); |
|
594 txNode->AddDevice (txDev1); |
|
595 Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> (); |
|
596 uint32_t netdev_idx = ipv4->AddInterface (txDev1); |
|
597 ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2")); |
|
598 ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); |
|
599 ipv4->SetUp (netdev_idx); |
|
600 } |
|
601 Ptr<SimpleNetDevice> txDev2; |
|
602 { |
|
603 txDev2 = CreateObject<SimpleNetDevice> (); |
|
604 txDev2->SetAddress (Mac48Address::Allocate ()); |
|
605 txNode->AddDevice (txDev2); |
|
606 Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> (); |
|
607 uint32_t netdev_idx = ipv4->AddInterface (txDev2); |
|
608 ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2")); |
|
609 ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); |
|
610 ipv4->SetUp (netdev_idx); |
|
611 } |
|
612 |
|
613 // link the two nodes |
|
614 Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> (); |
|
615 rxDev1->SetChannel (channel1); |
|
616 txDev1->SetChannel (channel1); |
|
617 |
|
618 Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> (); |
|
619 rxDev2->SetChannel (channel2); |
|
620 txDev2->SetChannel (channel2); |
|
621 |
|
622 |
|
623 // Create the UDP sockets |
|
624 Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> (); |
|
625 Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket (); |
|
626 NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0); |
|
627 rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this)); |
|
628 |
|
629 Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket (); |
|
630 rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this)); |
|
631 NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0); |
|
632 |
|
633 Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> (); |
|
634 Ptr<Socket> txSocket = txSocketFactory->CreateSocket (); |
|
635 |
|
636 // ------ Now the tests ------------ |
|
637 |
|
638 // Unicast test |
|
639 m_receivedPacket = Create<Packet> (); |
|
640 m_receivedPacket2 = Create<Packet> (); |
|
641 NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), |
|
642 InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123); |
|
643 Simulator::Run (); |
|
644 NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); |
|
645 NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it |
|
646 |
|
647 m_receivedPacket->RemoveAllTags (); |
|
648 m_receivedPacket2->RemoveAllTags (); |
|
649 |
|
650 // Simple broadcast test |
|
651 |
|
652 m_receivedPacket = Create<Packet> (); |
|
653 m_receivedPacket2 = Create<Packet> (); |
|
654 NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), |
|
655 InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123); |
|
656 Simulator::Run (); |
|
657 NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); |
|
658 // second socket should not receive it (it is bound specifically to the second interface's address |
|
659 NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); |
|
660 |
|
661 m_receivedPacket->RemoveAllTags (); |
|
662 m_receivedPacket2->RemoveAllTags (); |
|
663 |
|
664 // Broadcast test with multiple receiving sockets |
|
665 |
|
666 // When receiving broadcast packets, all sockets sockets bound to |
|
667 // the address/port should receive a copy of the same packet -- if |
|
668 // the socket address matches. |
|
669 rxSocket2->Dispose (); |
|
670 rxSocket2 = rxSocketFactory->CreateSocket (); |
|
671 rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this)); |
|
672 NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0); |
|
673 |
|
674 m_receivedPacket = Create<Packet> (); |
|
675 m_receivedPacket2 = Create<Packet> (); |
|
676 NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123), |
|
677 InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123); |
|
678 Simulator::Run (); |
|
679 NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); |
|
680 NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123); |
|
681 |
|
682 m_receivedPacket->RemoveAllTags (); |
|
683 m_receivedPacket2->RemoveAllTags (); |
|
684 |
|
685 Simulator::Destroy (); |
|
686 |
|
687 return result; |
|
688 } |
|
689 |
|
690 static UdpSocketImplTest gUdpSocketImplTest; |
|
691 |
|
692 }; // namespace ns3 |
|
693 |
|
694 #endif /* RUN_SELF_TESTS */ |
|