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