1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2007 Georgia Tech Research Corporation
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: Raj Bhattacharjea <raj.b@gatech.edu>
19 */
20
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 #include "ns3/nstime.h"
24 #include "ns3/boolean.h"
25 #include "ns3/object-vector.h"
26
27 #include "ns3/packet.h"
28 #include "ns3/node.h"
29 #include "ns3/simulator.h"
30 #include "ns3/ipv4-route.h"
31 #include "ns3/ipv6-route.h"
32
33 #include "tcp-l4-protocol.h"
34 #include "tcp-header.h"
35 #include "ipv4-end-point-demux.h"
36 #include "ipv6-end-point-demux.h"
37 #include "ipv4-end-point.h"
38 #include "ipv6-end-point.h"
39 #include "ipv4-l3-protocol.h"
40 #include "ipv6-l3-protocol.h"
41 #include "ipv6-routing-protocol.h"
42 #include "tcp-socket-factory-impl.h"
43 #include "tcp-socket-base.h"
44 #include "tcp-congestion-ops.h"
45 #include "tcp-cubic.h"
46 #include "tcp-recovery-ops.h"
47 #include "tcp-prr-recovery.h"
48 #include "rtt-estimator.h"
49
50 #include <vector>
51 #include <sstream>
52 #include <iomanip>
53
54 namespace ns3 {
55
56 NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
57
58 NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol);
59
60 //TcpL4Protocol stuff----------------------------------------------------------
61
62 #undef NS_LOG_APPEND_CONTEXT
63 #define NS_LOG_APPEND_CONTEXT \
64 if (m_node) { std::clog << " [node " << m_node->GetId () << "] "; }
65
66 /* see http://www.iana.org/assignments/protocol-numbers */
67 const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
68
69 TypeId
GetTypeId(void)70 TcpL4Protocol::GetTypeId (void)
71 {
72 static TypeId tid = TypeId ("ns3::TcpL4Protocol")
73 .SetParent<IpL4Protocol> ()
74 .SetGroupName ("Internet")
75 .AddConstructor<TcpL4Protocol> ()
76 .AddAttribute ("RttEstimatorType",
77 "Type of RttEstimator objects.",
78 TypeIdValue (RttMeanDeviation::GetTypeId ()),
79 MakeTypeIdAccessor (&TcpL4Protocol::m_rttTypeId),
80 MakeTypeIdChecker ())
81 .AddAttribute ("SocketType",
82 "Socket type of TCP objects.",
83 TypeIdValue (TcpCubic::GetTypeId ()),
84 MakeTypeIdAccessor (&TcpL4Protocol::m_congestionTypeId),
85 MakeTypeIdChecker ())
86 .AddAttribute ("RecoveryType",
87 "Recovery type of TCP objects.",
88 TypeIdValue (TcpPrrRecovery::GetTypeId ()),
89 MakeTypeIdAccessor (&TcpL4Protocol::m_recoveryTypeId),
90 MakeTypeIdChecker ())
91 .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
92 ObjectVectorValue (),
93 MakeObjectVectorAccessor (&TcpL4Protocol::m_sockets),
94 MakeObjectVectorChecker<TcpSocketBase> ())
95 ;
96 return tid;
97 }
98
TcpL4Protocol()99 TcpL4Protocol::TcpL4Protocol ()
100 : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
101 {
102 NS_LOG_FUNCTION (this);
103 }
104
~TcpL4Protocol()105 TcpL4Protocol::~TcpL4Protocol ()
106 {
107 NS_LOG_FUNCTION (this);
108 }
109
110 void
SetNode(Ptr<Node> node)111 TcpL4Protocol::SetNode (Ptr<Node> node)
112 {
113 NS_LOG_FUNCTION (this);
114 m_node = node;
115 }
116
117 void
NotifyNewAggregate()118 TcpL4Protocol::NotifyNewAggregate ()
119 {
120 NS_LOG_FUNCTION (this);
121 Ptr<Node> node = this->GetObject<Node> ();
122 Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
123 Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
124
125 if (m_node == 0)
126 {
127 if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
128 {
129 this->SetNode (node);
130 Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
131 tcpFactory->SetTcp (this);
132 node->AggregateObject (tcpFactory);
133 }
134 }
135
136 // We set at least one of our 2 down targets to the IPv4/IPv6 send
137 // functions. Since these functions have different prototypes, we
138 // need to keep track of whether we are connected to an IPv4 or
139 // IPv6 lower layer and call the appropriate one.
140
141 if (ipv4 != 0 && m_downTarget.IsNull ())
142 {
143 ipv4->Insert (this);
144 this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
145 }
146 if (ipv6 != 0 && m_downTarget6.IsNull ())
147 {
148 ipv6->Insert (this);
149 this->SetDownTarget6 (MakeCallback (&Ipv6::Send, ipv6));
150 }
151 IpL4Protocol::NotifyNewAggregate ();
152 }
153
154 int
GetProtocolNumber(void) const155 TcpL4Protocol::GetProtocolNumber (void) const
156 {
157 return PROT_NUMBER;
158 }
159
160 void
DoDispose(void)161 TcpL4Protocol::DoDispose (void)
162 {
163 NS_LOG_FUNCTION (this);
164 m_sockets.clear ();
165
166 if (m_endPoints != 0)
167 {
168 delete m_endPoints;
169 m_endPoints = 0;
170 }
171
172 if (m_endPoints6 != 0)
173 {
174 delete m_endPoints6;
175 m_endPoints6 = 0;
176 }
177
178 m_node = 0;
179 m_downTarget.Nullify ();
180 m_downTarget6.Nullify ();
181 IpL4Protocol::DoDispose ();
182 }
183
184 Ptr<Socket>
CreateSocket(TypeId congestionTypeId)185 TcpL4Protocol::CreateSocket (TypeId congestionTypeId)
186 {
187 return CreateSocket (congestionTypeId, m_recoveryTypeId);
188 }
189
190 Ptr<Socket>
CreateSocket(TypeId congestionTypeId,TypeId recoveryTypeId)191 TcpL4Protocol::CreateSocket (TypeId congestionTypeId, TypeId recoveryTypeId)
192 {
193 NS_LOG_FUNCTION (this << congestionTypeId.GetName ());
194 ObjectFactory rttFactory;
195 ObjectFactory congestionAlgorithmFactory;
196 ObjectFactory recoveryAlgorithmFactory;
197 rttFactory.SetTypeId (m_rttTypeId);
198 congestionAlgorithmFactory.SetTypeId (congestionTypeId);
199 recoveryAlgorithmFactory.SetTypeId (recoveryTypeId);
200
201 Ptr<RttEstimator> rtt = rttFactory.Create<RttEstimator> ();
202 Ptr<TcpSocketBase> socket = CreateObject<TcpSocketBase> ();
203 Ptr<TcpCongestionOps> algo = congestionAlgorithmFactory.Create<TcpCongestionOps> ();
204 Ptr<TcpRecoveryOps> recovery = recoveryAlgorithmFactory.Create<TcpRecoveryOps> ();
205
206 socket->SetNode (m_node);
207 socket->SetTcp (this);
208 socket->SetRtt (rtt);
209 socket->SetCongestionControlAlgorithm (algo);
210 socket->SetRecoveryAlgorithm (recovery);
211
212 m_sockets.push_back (socket);
213 return socket;
214 }
215
216 Ptr<Socket>
CreateSocket(void)217 TcpL4Protocol::CreateSocket (void)
218 {
219 return CreateSocket (m_congestionTypeId, m_recoveryTypeId);
220 }
221
222 Ipv4EndPoint *
Allocate(void)223 TcpL4Protocol::Allocate (void)
224 {
225 NS_LOG_FUNCTION (this);
226 return m_endPoints->Allocate ();
227 }
228
229 Ipv4EndPoint *
Allocate(Ipv4Address address)230 TcpL4Protocol::Allocate (Ipv4Address address)
231 {
232 NS_LOG_FUNCTION (this << address);
233 return m_endPoints->Allocate (address);
234 }
235
236 Ipv4EndPoint *
Allocate(Ptr<NetDevice> boundNetDevice,uint16_t port)237 TcpL4Protocol::Allocate (Ptr<NetDevice> boundNetDevice, uint16_t port)
238 {
239 NS_LOG_FUNCTION (this << boundNetDevice << port);
240 return m_endPoints->Allocate (boundNetDevice, port);
241 }
242
243 Ipv4EndPoint *
Allocate(Ptr<NetDevice> boundNetDevice,Ipv4Address address,uint16_t port)244 TcpL4Protocol::Allocate (Ptr<NetDevice> boundNetDevice, Ipv4Address address, uint16_t port)
245 {
246 NS_LOG_FUNCTION (this << boundNetDevice << address << port);
247 return m_endPoints->Allocate (boundNetDevice, address, port);
248 }
249
250 Ipv4EndPoint *
Allocate(Ptr<NetDevice> boundNetDevice,Ipv4Address localAddress,uint16_t localPort,Ipv4Address peerAddress,uint16_t peerPort)251 TcpL4Protocol::Allocate (Ptr<NetDevice> boundNetDevice,
252 Ipv4Address localAddress, uint16_t localPort,
253 Ipv4Address peerAddress, uint16_t peerPort)
254 {
255 NS_LOG_FUNCTION (this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
256 return m_endPoints->Allocate (boundNetDevice,
257 localAddress, localPort,
258 peerAddress, peerPort);
259 }
260
261 void
DeAllocate(Ipv4EndPoint * endPoint)262 TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
263 {
264 NS_LOG_FUNCTION (this << endPoint);
265 m_endPoints->DeAllocate (endPoint);
266 }
267
268 Ipv6EndPoint *
Allocate6(void)269 TcpL4Protocol::Allocate6 (void)
270 {
271 NS_LOG_FUNCTION (this);
272 return m_endPoints6->Allocate ();
273 }
274
275 Ipv6EndPoint *
Allocate6(Ipv6Address address)276 TcpL4Protocol::Allocate6 (Ipv6Address address)
277 {
278 NS_LOG_FUNCTION (this << address);
279 return m_endPoints6->Allocate (address);
280 }
281
282 Ipv6EndPoint *
Allocate6(Ptr<NetDevice> boundNetDevice,uint16_t port)283 TcpL4Protocol::Allocate6 (Ptr<NetDevice> boundNetDevice, uint16_t port)
284 {
285 NS_LOG_FUNCTION (this << boundNetDevice << port);
286 return m_endPoints6->Allocate (boundNetDevice, port);
287 }
288
289 Ipv6EndPoint *
Allocate6(Ptr<NetDevice> boundNetDevice,Ipv6Address address,uint16_t port)290 TcpL4Protocol::Allocate6 (Ptr<NetDevice> boundNetDevice, Ipv6Address address, uint16_t port)
291 {
292 NS_LOG_FUNCTION (this << boundNetDevice << address << port);
293 return m_endPoints6->Allocate (boundNetDevice, address, port);
294 }
295
296 Ipv6EndPoint *
Allocate6(Ptr<NetDevice> boundNetDevice,Ipv6Address localAddress,uint16_t localPort,Ipv6Address peerAddress,uint16_t peerPort)297 TcpL4Protocol::Allocate6 (Ptr<NetDevice> boundNetDevice,
298 Ipv6Address localAddress, uint16_t localPort,
299 Ipv6Address peerAddress, uint16_t peerPort)
300 {
301 NS_LOG_FUNCTION (this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
302 return m_endPoints6->Allocate (boundNetDevice,
303 localAddress, localPort,
304 peerAddress, peerPort);
305 }
306
307 void
DeAllocate(Ipv6EndPoint * endPoint)308 TcpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
309 {
310 NS_LOG_FUNCTION (this << endPoint);
311 m_endPoints6->DeAllocate (endPoint);
312 }
313
314 void
ReceiveIcmp(Ipv4Address icmpSource,uint8_t icmpTtl,uint8_t icmpType,uint8_t icmpCode,uint32_t icmpInfo,Ipv4Address payloadSource,Ipv4Address payloadDestination,const uint8_t payload[8])315 TcpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
316 uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
317 Ipv4Address payloadSource,Ipv4Address payloadDestination,
318 const uint8_t payload[8])
319 {
320 NS_LOG_FUNCTION (this << icmpSource << (uint16_t) icmpTtl << (uint16_t) icmpType << (uint16_t) icmpCode << icmpInfo
321 << payloadSource << payloadDestination);
322 uint16_t src, dst;
323 src = payload[0] << 8;
324 src |= payload[1];
325 dst = payload[2] << 8;
326 dst |= payload[3];
327
328 Ipv4EndPoint *endPoint = m_endPoints->SimpleLookup (payloadSource, src, payloadDestination, dst);
329 if (endPoint != 0)
330 {
331 endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
332 }
333 else
334 {
335 NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
336 ", destination=" << payloadDestination <<
337 ", src=" << src << ", dst=" << dst);
338 }
339 }
340
341 void
ReceiveIcmp(Ipv6Address icmpSource,uint8_t icmpTtl,uint8_t icmpType,uint8_t icmpCode,uint32_t icmpInfo,Ipv6Address payloadSource,Ipv6Address payloadDestination,const uint8_t payload[8])342 TcpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
343 uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
344 Ipv6Address payloadSource,Ipv6Address payloadDestination,
345 const uint8_t payload[8])
346 {
347 NS_LOG_FUNCTION (this << icmpSource << (uint16_t) icmpTtl << (uint16_t) icmpType << (uint16_t) icmpCode << icmpInfo
348 << payloadSource << payloadDestination);
349 uint16_t src, dst;
350 src = payload[0] << 8;
351 src |= payload[1];
352 dst = payload[2] << 8;
353 dst |= payload[3];
354
355 Ipv6EndPoint *endPoint = m_endPoints6->SimpleLookup (payloadSource, src, payloadDestination, dst);
356 if (endPoint != 0)
357 {
358 endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
359 }
360 else
361 {
362 NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
363 ", destination=" << payloadDestination <<
364 ", src=" << src << ", dst=" << dst);
365 }
366 }
367
368 enum IpL4Protocol::RxStatus
PacketReceived(Ptr<Packet> packet,TcpHeader & incomingTcpHeader,const Address & source,const Address & destination)369 TcpL4Protocol::PacketReceived (Ptr<Packet> packet, TcpHeader &incomingTcpHeader,
370 const Address &source, const Address &destination)
371 {
372 NS_LOG_FUNCTION (this << packet << incomingTcpHeader << source << destination);
373
374 if (Node::ChecksumEnabled ())
375 {
376 incomingTcpHeader.EnableChecksums ();
377 incomingTcpHeader.InitializeChecksum (source, destination, PROT_NUMBER);
378 }
379
380 packet->PeekHeader (incomingTcpHeader);
381
382 NS_LOG_LOGIC ("TcpL4Protocol " << this
383 << " receiving seq " << incomingTcpHeader.GetSequenceNumber ()
384 << " ack " << incomingTcpHeader.GetAckNumber ()
385 << " flags "<< TcpHeader::FlagsToString (incomingTcpHeader.GetFlags ())
386 << " data size " << packet->GetSize ());
387
388 if (!incomingTcpHeader.IsChecksumOk ())
389 {
390 NS_LOG_INFO ("Bad checksum, dropping packet!");
391 return IpL4Protocol::RX_CSUM_FAILED;
392 }
393
394 return IpL4Protocol::RX_OK;
395 }
396
397 void
NoEndPointsFound(const TcpHeader & incomingHeader,const Address & incomingSAddr,const Address & incomingDAddr)398 TcpL4Protocol::NoEndPointsFound (const TcpHeader &incomingHeader,
399 const Address &incomingSAddr,
400 const Address &incomingDAddr)
401 {
402 NS_LOG_FUNCTION (this << incomingHeader << incomingSAddr << incomingDAddr);
403
404 if (!(incomingHeader.GetFlags () & TcpHeader::RST))
405 {
406 // build a RST packet and send
407 Ptr<Packet> rstPacket = Create<Packet> ();
408 TcpHeader outgoingTcpHeader;
409
410 if (incomingHeader.GetFlags () & TcpHeader::ACK)
411 {
412 // ACK bit was set
413 outgoingTcpHeader.SetFlags (TcpHeader::RST);
414 outgoingTcpHeader.SetSequenceNumber (incomingHeader.GetAckNumber ());
415 }
416 else
417 {
418 outgoingTcpHeader.SetFlags (TcpHeader::RST | TcpHeader::ACK);
419 outgoingTcpHeader.SetSequenceNumber (SequenceNumber32 (0));
420 outgoingTcpHeader.SetAckNumber (incomingHeader.GetSequenceNumber () +
421 SequenceNumber32 (1));
422 }
423
424 // Remember that parameters refer to the incoming packet; in reply,
425 // we need to swap src/dst
426
427 outgoingTcpHeader.SetSourcePort (incomingHeader.GetDestinationPort ());
428 outgoingTcpHeader.SetDestinationPort (incomingHeader.GetSourcePort ());
429
430 SendPacket (rstPacket, outgoingTcpHeader, incomingDAddr, incomingSAddr);
431 }
432 }
433
434 enum IpL4Protocol::RxStatus
Receive(Ptr<Packet> packet,Ipv4Header const & incomingIpHeader,Ptr<Ipv4Interface> incomingInterface)435 TcpL4Protocol::Receive (Ptr<Packet> packet,
436 Ipv4Header const &incomingIpHeader,
437 Ptr<Ipv4Interface> incomingInterface)
438 {
439 NS_LOG_FUNCTION (this << packet << incomingIpHeader << incomingInterface);
440
441 TcpHeader incomingTcpHeader;
442 IpL4Protocol::RxStatus checksumControl;
443
444 checksumControl = PacketReceived (packet, incomingTcpHeader,
445 incomingIpHeader.GetSource (),
446 incomingIpHeader.GetDestination ());
447
448 if (checksumControl != IpL4Protocol::RX_OK)
449 {
450 return checksumControl;
451 }
452
453 Ipv4EndPointDemux::EndPoints endPoints;
454 endPoints = m_endPoints->Lookup (incomingIpHeader.GetDestination (),
455 incomingTcpHeader.GetDestinationPort (),
456 incomingIpHeader.GetSource (),
457 incomingTcpHeader.GetSourcePort (),
458 incomingInterface);
459
460 if (endPoints.empty ())
461 {
462 if (this->GetObject<Ipv6L3Protocol> () != 0)
463 {
464 NS_LOG_LOGIC (" No Ipv4 endpoints matched on TcpL4Protocol, trying Ipv6 " << this);
465 Ptr<Ipv6Interface> fakeInterface;
466 Ipv6Header ipv6Header;
467 Ipv6Address src, dst;
468
469 src = Ipv6Address::MakeIpv4MappedAddress (incomingIpHeader.GetSource ());
470 dst = Ipv6Address::MakeIpv4MappedAddress (incomingIpHeader.GetDestination ());
471 ipv6Header.SetSource (src);
472 ipv6Header.SetDestination (dst);
473 return (this->Receive (packet, ipv6Header, fakeInterface));
474 }
475
476 NS_LOG_LOGIC ("TcpL4Protocol " << this << " received a packet but"
477 " no endpoints matched." <<
478 " destination IP: " << incomingIpHeader.GetDestination () <<
479 " destination port: "<< incomingTcpHeader.GetDestinationPort () <<
480 " source IP: " << incomingIpHeader.GetSource () <<
481 " source port: "<< incomingTcpHeader.GetSourcePort ());
482
483 NoEndPointsFound (incomingTcpHeader, incomingIpHeader.GetSource (),
484 incomingIpHeader.GetDestination ());
485
486 return IpL4Protocol::RX_ENDPOINT_CLOSED;
487
488 }
489
490 NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
491 NS_LOG_LOGIC ("TcpL4Protocol " << this << " received a packet and"
492 " now forwarding it up to endpoint/socket");
493
494 (*endPoints.begin ())->ForwardUp (packet, incomingIpHeader,
495 incomingTcpHeader.GetSourcePort (),
496 incomingInterface);
497
498 return IpL4Protocol::RX_OK;
499 }
500
501 enum IpL4Protocol::RxStatus
Receive(Ptr<Packet> packet,Ipv6Header const & incomingIpHeader,Ptr<Ipv6Interface> interface)502 TcpL4Protocol::Receive (Ptr<Packet> packet,
503 Ipv6Header const &incomingIpHeader,
504 Ptr<Ipv6Interface> interface)
505 {
506 NS_LOG_FUNCTION (this << packet << incomingIpHeader.GetSource () <<
507 incomingIpHeader.GetDestination ());
508
509 TcpHeader incomingTcpHeader;
510 IpL4Protocol::RxStatus checksumControl;
511
512 // If we are receiving a v4-mapped packet, we will re-calculate the TCP checksum
513 // Is it worth checking every received "v6" packet to see if it is v4-mapped in
514 // order to avoid re-calculating TCP checksums for v4-mapped packets?
515
516 checksumControl = PacketReceived (packet, incomingTcpHeader,
517 incomingIpHeader.GetSource (),
518 incomingIpHeader.GetDestination ());
519
520 if (checksumControl != IpL4Protocol::RX_OK)
521 {
522 return checksumControl;
523 }
524
525 Ipv6EndPointDemux::EndPoints endPoints =
526 m_endPoints6->Lookup (incomingIpHeader.GetDestination (),
527 incomingTcpHeader.GetDestinationPort (),
528 incomingIpHeader.GetSource (),
529 incomingTcpHeader.GetSourcePort (), interface);
530 if (endPoints.empty ())
531 {
532 NS_LOG_LOGIC ("TcpL4Protocol " << this << " received a packet but"
533 " no endpoints matched." <<
534 " destination IP: " << incomingIpHeader.GetDestination () <<
535 " destination port: "<< incomingTcpHeader.GetDestinationPort () <<
536 " source IP: " << incomingIpHeader.GetSource () <<
537 " source port: "<< incomingTcpHeader.GetSourcePort ());
538
539 NoEndPointsFound (incomingTcpHeader, incomingIpHeader.GetSource (),
540 incomingIpHeader.GetDestination ());
541
542 return IpL4Protocol::RX_ENDPOINT_CLOSED;
543 }
544
545 NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
546 NS_LOG_LOGIC ("TcpL4Protocol " << this << " received a packet and"
547 " now forwarding it up to endpoint/socket");
548
549 (*endPoints.begin ())->ForwardUp (packet, incomingIpHeader,
550 incomingTcpHeader.GetSourcePort (), interface);
551
552 return IpL4Protocol::RX_OK;
553 }
554
555 void
SendPacketV4(Ptr<Packet> packet,const TcpHeader & outgoing,const Ipv4Address & saddr,const Ipv4Address & daddr,Ptr<NetDevice> oif) const556 TcpL4Protocol::SendPacketV4 (Ptr<Packet> packet, const TcpHeader &outgoing,
557 const Ipv4Address &saddr, const Ipv4Address &daddr,
558 Ptr<NetDevice> oif) const
559 {
560 NS_LOG_FUNCTION (this << packet << saddr << daddr << oif);
561 NS_LOG_LOGIC ("TcpL4Protocol " << this
562 << " sending seq " << outgoing.GetSequenceNumber ()
563 << " ack " << outgoing.GetAckNumber ()
564 << " flags " << TcpHeader::FlagsToString (outgoing.GetFlags ())
565 << " data size " << packet->GetSize ());
566 // XXX outgoingHeader cannot be logged
567
568 TcpHeader outgoingHeader = outgoing;
569 /** \todo UrgentPointer */
570 /* outgoingHeader.SetUrgentPointer (0); */
571 if (Node::ChecksumEnabled ())
572 {
573 outgoingHeader.EnableChecksums ();
574 }
575 outgoingHeader.InitializeChecksum (saddr, daddr, PROT_NUMBER);
576
577 packet->AddHeader (outgoingHeader);
578
579 Ptr<Ipv4> ipv4 =
580 m_node->GetObject<Ipv4> ();
581 if (ipv4 != 0)
582 {
583 Ipv4Header header;
584 header.SetSource (saddr);
585 header.SetDestination (daddr);
586 header.SetProtocol (PROT_NUMBER);
587 Socket::SocketErrno errno_;
588 Ptr<Ipv4Route> route;
589 if (ipv4->GetRoutingProtocol () != 0)
590 {
591 route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
592 }
593 else
594 {
595 NS_LOG_ERROR ("No IPV4 Routing Protocol");
596 route = 0;
597 }
598 m_downTarget (packet, saddr, daddr, PROT_NUMBER, route);
599 }
600 else
601 {
602 NS_FATAL_ERROR ("Trying to use Tcp on a node without an Ipv4 interface");
603 }
604 }
605
606 void
SendPacketV6(Ptr<Packet> packet,const TcpHeader & outgoing,const Ipv6Address & saddr,const Ipv6Address & daddr,Ptr<NetDevice> oif) const607 TcpL4Protocol::SendPacketV6 (Ptr<Packet> packet, const TcpHeader &outgoing,
608 const Ipv6Address &saddr, const Ipv6Address &daddr,
609 Ptr<NetDevice> oif) const
610 {
611 NS_LOG_FUNCTION (this << packet << saddr << daddr << oif);
612 NS_LOG_LOGIC ("TcpL4Protocol " << this
613 << " sending seq " << outgoing.GetSequenceNumber ()
614 << " ack " << outgoing.GetAckNumber ()
615 << " flags " << TcpHeader::FlagsToString (outgoing.GetFlags ())
616 << " data size " << packet->GetSize ());
617 // XXX outgoingHeader cannot be logged
618
619 if (daddr.IsIpv4MappedAddress ())
620 {
621 return (SendPacket (packet, outgoing, saddr.GetIpv4MappedAddress (), daddr.GetIpv4MappedAddress (), oif));
622 }
623 TcpHeader outgoingHeader = outgoing;
624 /** \todo UrgentPointer */
625 /* outgoingHeader.SetUrgentPointer (0); */
626 if (Node::ChecksumEnabled ())
627 {
628 outgoingHeader.EnableChecksums ();
629 }
630 outgoingHeader.InitializeChecksum (saddr, daddr, PROT_NUMBER);
631
632 packet->AddHeader (outgoingHeader);
633
634 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
635 if (ipv6 != 0)
636 {
637 Ipv6Header header;
638 header.SetSource (saddr);
639 header.SetDestination (daddr);
640 header.SetNextHeader (PROT_NUMBER);
641 Socket::SocketErrno errno_;
642 Ptr<Ipv6Route> route;
643 if (ipv6->GetRoutingProtocol () != 0)
644 {
645 route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
646 }
647 else
648 {
649 NS_LOG_ERROR ("No IPV6 Routing Protocol");
650 route = 0;
651 }
652 m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
653 }
654 else
655 {
656 NS_FATAL_ERROR ("Trying to use Tcp on a node without an Ipv6 interface");
657 }
658 }
659
660 void
SendPacket(Ptr<Packet> pkt,const TcpHeader & outgoing,const Address & saddr,const Address & daddr,Ptr<NetDevice> oif) const661 TcpL4Protocol::SendPacket (Ptr<Packet> pkt, const TcpHeader &outgoing,
662 const Address &saddr, const Address &daddr,
663 Ptr<NetDevice> oif) const
664 {
665 NS_LOG_FUNCTION (this << pkt << outgoing << saddr << daddr << oif);
666 if (Ipv4Address::IsMatchingType (saddr))
667 {
668 NS_ASSERT (Ipv4Address::IsMatchingType (daddr));
669
670 SendPacketV4 (pkt, outgoing, Ipv4Address::ConvertFrom (saddr),
671 Ipv4Address::ConvertFrom (daddr), oif);
672
673 return;
674 }
675 else if (Ipv6Address::IsMatchingType (saddr))
676 {
677 NS_ASSERT (Ipv6Address::IsMatchingType (daddr));
678
679 SendPacketV6 (pkt, outgoing, Ipv6Address::ConvertFrom (saddr),
680 Ipv6Address::ConvertFrom (daddr), oif);
681
682 return;
683 }
684 else if (InetSocketAddress::IsMatchingType (saddr))
685 {
686 InetSocketAddress s = InetSocketAddress::ConvertFrom (saddr);
687 InetSocketAddress d = InetSocketAddress::ConvertFrom (daddr);
688
689 SendPacketV4 (pkt, outgoing, s.GetIpv4 (), d.GetIpv4 (), oif);
690
691 return;
692 }
693 else if (Inet6SocketAddress::IsMatchingType (saddr))
694 {
695 Inet6SocketAddress s = Inet6SocketAddress::ConvertFrom (saddr);
696 Inet6SocketAddress d = Inet6SocketAddress::ConvertFrom (daddr);
697
698 SendPacketV6 (pkt, outgoing, s.GetIpv6 (), d.GetIpv6 (), oif);
699
700 return;
701 }
702
703 NS_FATAL_ERROR ("Trying to send a packet without IP addresses");
704 }
705
706 void
AddSocket(Ptr<TcpSocketBase> socket)707 TcpL4Protocol::AddSocket (Ptr<TcpSocketBase> socket)
708 {
709 NS_LOG_FUNCTION (this << socket);
710 std::vector<Ptr<TcpSocketBase> >::iterator it = m_sockets.begin ();
711
712 while (it != m_sockets.end ())
713 {
714 if (*it == socket)
715 {
716 return;
717 }
718
719 ++it;
720 }
721
722 m_sockets.push_back (socket);
723 }
724
725 bool
RemoveSocket(Ptr<TcpSocketBase> socket)726 TcpL4Protocol::RemoveSocket (Ptr<TcpSocketBase> socket)
727 {
728 NS_LOG_FUNCTION (this << socket);
729 std::vector<Ptr<TcpSocketBase> >::iterator it = m_sockets.begin ();
730
731 while (it != m_sockets.end ())
732 {
733 if (*it == socket)
734 {
735 m_sockets.erase (it);
736 return true;
737 }
738
739 ++it;
740 }
741
742 return false;
743 }
744
745 void
SetDownTarget(IpL4Protocol::DownTargetCallback callback)746 TcpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
747 {
748 m_downTarget = callback;
749 }
750
751 IpL4Protocol::DownTargetCallback
GetDownTarget(void) const752 TcpL4Protocol::GetDownTarget (void) const
753 {
754 return m_downTarget;
755 }
756
757 void
SetDownTarget6(IpL4Protocol::DownTargetCallback6 callback)758 TcpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
759 {
760 m_downTarget6 = callback;
761 }
762
763 IpL4Protocol::DownTargetCallback6
GetDownTarget6(void) const764 TcpL4Protocol::GetDownTarget6 (void) const
765 {
766 return m_downTarget6;
767 }
768
769 } // namespace ns3
770
771