A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tcp-l4-protocol.cc
Go to the documentation of this file.
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"
43 #include "tcp-newreno.h"
44 #include "rtt-estimator.h"
45 
46 #include <vector>
47 #include <sstream>
48 #include <iomanip>
49 
50 NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
51 
52 namespace ns3 {
53 
54 NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol);
55 
56 //TcpL4Protocol stuff----------------------------------------------------------
57 
58 #undef NS_LOG_APPEND_CONTEXT
59 #define NS_LOG_APPEND_CONTEXT \
60  if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
61 
62 /* see http://www.iana.org/assignments/protocol-numbers */
63 const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
64 
65 TypeId
67 {
68  static TypeId tid = TypeId ("ns3::TcpL4Protocol")
70  .AddConstructor<TcpL4Protocol> ()
71  .AddAttribute ("RttEstimatorType",
72  "Type of RttEstimator objects.",
74  MakeTypeIdAccessor (&TcpL4Protocol::m_rttTypeId),
75  MakeTypeIdChecker ())
76  .AddAttribute ("SocketType",
77  "Socket type of TCP objects.",
79  MakeTypeIdAccessor (&TcpL4Protocol::m_socketTypeId),
80  MakeTypeIdChecker ())
81  .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
84  MakeObjectVectorChecker<TcpSocketBase> ())
85  ;
86  return tid;
87 }
88 
90  : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
91 {
93  NS_LOG_LOGIC ("Made a TcpL4Protocol "<<this);
94 }
95 
97 {
99 }
100 
101 void
103 {
104  m_node = node;
105 }
106 
107 /*
108  * This method is called by AddAgregate and completes the aggregation
109  * by setting the node in the TCP stack, link it to the ipv4 stack and
110  * adding TCP socket factory to the node.
111  */
112 void
114 {
115  Ptr<Node> node = this->GetObject<Node> ();
116  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
118 
119  if (m_node == 0)
120  {
121  if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
122  {
123  this->SetNode (node);
124  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
125  tcpFactory->SetTcp (this);
126  node->AggregateObject (tcpFactory);
127  }
128  }
129 
130  // We set at least one of our 2 down targets to the IPv4/IPv6 send
131  // functions. Since these functions have different prototypes, we
132  // need to keep track of whether we are connected to an IPv4 or
133  // IPv6 lower layer and call the appropriate one.
134 
135  if (ipv4 != 0 && m_downTarget.IsNull ())
136  {
137  ipv4->Insert(this);
138  this->SetDownTarget(MakeCallback(&Ipv4::Send, ipv4));
139  }
140  if (ipv6 != 0 && m_downTarget6.IsNull ())
141  {
142  ipv6->Insert(this);
144  }
146 }
147 
148 int
150 {
151  return PROT_NUMBER;
152 }
153 
154 void
156 {
158  m_sockets.clear ();
159 
160  if (m_endPoints != 0)
161  {
162  delete m_endPoints;
163  m_endPoints = 0;
164  }
165 
166  if (m_endPoints6 != 0)
167  {
168  delete m_endPoints6;
169  m_endPoints6 = 0;
170  }
171 
172  m_node = 0;
176 }
177 
180 {
182  ObjectFactory rttFactory;
183  ObjectFactory socketFactory;
184  rttFactory.SetTypeId (m_rttTypeId);
185  socketFactory.SetTypeId (socketTypeId);
186  Ptr<RttEstimator> rtt = rttFactory.Create<RttEstimator> ();
187  Ptr<TcpSocketBase> socket = socketFactory.Create<TcpSocketBase> ();
188  socket->SetNode (m_node);
189  socket->SetTcp (this);
190  socket->SetRtt (rtt);
191  return socket;
192 }
193 
196 {
197  return CreateSocket (m_socketTypeId);
198 }
199 
200 Ipv4EndPoint *
202 {
204  return m_endPoints->Allocate ();
205 }
206 
207 Ipv4EndPoint *
209 {
210  NS_LOG_FUNCTION (this << address);
211  return m_endPoints->Allocate (address);
212 }
213 
214 Ipv4EndPoint *
216 {
217  NS_LOG_FUNCTION (this << port);
218  return m_endPoints->Allocate (port);
219 }
220 
221 Ipv4EndPoint *
223 {
224  NS_LOG_FUNCTION (this << address << port);
225  return m_endPoints->Allocate (address, port);
226 }
227 
228 Ipv4EndPoint *
229 TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
230  Ipv4Address peerAddress, uint16_t peerPort)
231 {
232  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
233  return m_endPoints->Allocate (localAddress, localPort,
234  peerAddress, peerPort);
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION (this << endPoint);
241  m_endPoints->DeAllocate (endPoint);
242 }
243 
244 Ipv6EndPoint *
246 {
248  return m_endPoints6->Allocate ();
249 }
250 
251 Ipv6EndPoint *
253 {
254  NS_LOG_FUNCTION (this << address);
255  return m_endPoints6->Allocate (address);
256 }
257 
258 Ipv6EndPoint *
260 {
261  NS_LOG_FUNCTION (this << port);
262  return m_endPoints6->Allocate (port);
263 }
264 
265 Ipv6EndPoint *
267 {
268  NS_LOG_FUNCTION (this << address << port);
269  return m_endPoints6->Allocate (address, port);
270 }
271 
272 Ipv6EndPoint *
273 TcpL4Protocol::Allocate6 (Ipv6Address localAddress, uint16_t localPort,
274  Ipv6Address peerAddress, uint16_t peerPort)
275 {
276  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
277  return m_endPoints6->Allocate (localAddress, localPort,
278  peerAddress, peerPort);
279 }
280 
281 void
283 {
284  NS_LOG_FUNCTION (this << endPoint);
285  m_endPoints6->DeAllocate (endPoint);
286 }
287 
290  Ipv4Header const &ipHeader,
291  Ptr<Ipv4Interface> incomingInterface)
292 {
293  NS_LOG_FUNCTION (this << packet << ipHeader << incomingInterface);
294 
295  TcpHeader tcpHeader;
296  if(Node::ChecksumEnabled ())
297  {
298  tcpHeader.EnableChecksums ();
299  tcpHeader.InitializeChecksum (ipHeader.GetSource (), ipHeader.GetDestination (), PROT_NUMBER);
300  }
301 
302  packet->PeekHeader (tcpHeader);
303 
304  NS_LOG_LOGIC ("TcpL4Protocol " << this
305  << " receiving seq " << tcpHeader.GetSequenceNumber ()
306  << " ack " << tcpHeader.GetAckNumber ()
307  << " flags "<< std::hex << (int)tcpHeader.GetFlags () << std::dec
308  << " data size " << packet->GetSize ());
309 
310  if(!tcpHeader.IsChecksumOk ())
311  {
312  NS_LOG_INFO ("Bad checksum, dropping packet!");
314  }
315 
316  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
317  Ipv4EndPointDemux::EndPoints endPoints =
318  m_endPoints->Lookup (ipHeader.GetDestination (), tcpHeader.GetDestinationPort (),
319  ipHeader.GetSource (), tcpHeader.GetSourcePort (),incomingInterface);
320  if (endPoints.empty ())
321  {
322  if (this->GetObject<Ipv6L3Protocol> () != 0)
323  {
324  NS_LOG_LOGIC (" No Ipv4 endpoints matched on TcpL4Protocol, trying Ipv6 "<<this);
325  Ptr<Ipv6Interface> fakeInterface;
328  return (this->Receive (packet, src, dst, fakeInterface));
329  }
330 
331  NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<<this);
332  std::ostringstream oss;
333  oss<<" destination IP: ";
334  ipHeader.GetDestination ().Print (oss);
335  oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
336  ipHeader.GetSource ().Print (oss);
337  oss<<" source port: "<<tcpHeader.GetSourcePort ();
338  NS_LOG_LOGIC (oss.str ());
339 
340  if (!(tcpHeader.GetFlags () & TcpHeader::RST))
341  {
342  // build a RST packet and send
343  Ptr<Packet> rstPacket = Create<Packet> ();
344  TcpHeader header;
345  if (tcpHeader.GetFlags () & TcpHeader::ACK)
346  {
347  // ACK bit was set
348  header.SetFlags (TcpHeader::RST);
349  header.SetSequenceNumber (header.GetAckNumber ());
350  }
351  else
352  {
353  header.SetFlags (TcpHeader::RST | TcpHeader::ACK);
354  header.SetSequenceNumber (SequenceNumber32 (0));
355  header.SetAckNumber (header.GetSequenceNumber () + SequenceNumber32 (1));
356  }
357  header.SetSourcePort (tcpHeader.GetDestinationPort ());
358  header.SetDestinationPort (tcpHeader.GetSourcePort ());
359  SendPacket (rstPacket, header, ipHeader.GetDestination (), ipHeader.GetSource ());
361  }
362  else
363  {
365  }
366  }
367  NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
368  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
369  (*endPoints.begin ())->ForwardUp (packet, ipHeader, tcpHeader.GetSourcePort (),
370  incomingInterface);
371  return IpL4Protocol::RX_OK;
372 }
373 
376  Ipv6Address &src,
377  Ipv6Address &dst,
378  Ptr<Ipv6Interface> interface)
379 {
380  NS_LOG_FUNCTION (this << packet << src << dst);
381 
382  TcpHeader tcpHeader;
383 
384  // If we are receving a v4-mapped packet, we will re-calculate the TCP checksum
385  // Is it worth checking every received "v6" packet to see if it is v4-mapped in
386  // order to avoid re-calculating TCP checksums for v4-mapped packets?
387 
388  if(Node::ChecksumEnabled ())
389  {
390  tcpHeader.EnableChecksums ();
391  tcpHeader.InitializeChecksum (src, dst, PROT_NUMBER);
392  }
393 
394  packet->PeekHeader (tcpHeader);
395 
396  NS_LOG_LOGIC ("TcpL4Protocol " << this
397  << " receiving seq " << tcpHeader.GetSequenceNumber ()
398  << " ack " << tcpHeader.GetAckNumber ()
399  << " flags "<< std::hex << (int)tcpHeader.GetFlags () << std::dec
400  << " data size " << packet->GetSize ());
401 
402  if(!tcpHeader.IsChecksumOk ())
403  {
404  NS_LOG_INFO ("Bad checksum, dropping packet!");
406  }
407 
408  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
409  Ipv6EndPointDemux::EndPoints endPoints =
410  m_endPoints6->Lookup (dst, tcpHeader.GetDestinationPort (),
411  src, tcpHeader.GetSourcePort (),interface);
412  if (endPoints.empty ())
413  {
414  NS_LOG_LOGIC (" No IPv6 endpoints matched on TcpL4Protocol "<<this);
415  std::ostringstream oss;
416  oss<<" destination IP: ";
417  dst.Print (oss);
418  oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
419  src.Print (oss);
420  oss<<" source port: "<<tcpHeader.GetSourcePort ();
421  NS_LOG_LOGIC (oss.str ());
422 
423  if (!(tcpHeader.GetFlags () & TcpHeader::RST))
424  {
425  // build a RST packet and send
426  Ptr<Packet> rstPacket = Create<Packet> ();
427  TcpHeader header;
428  if (tcpHeader.GetFlags () & TcpHeader::ACK)
429  {
430  // ACK bit was set
431  header.SetFlags (TcpHeader::RST);
432  header.SetSequenceNumber (header.GetAckNumber ());
433  }
434  else
435  {
436  header.SetFlags (TcpHeader::RST | TcpHeader::ACK);
437  header.SetSequenceNumber (SequenceNumber32 (0));
438  header.SetAckNumber (header.GetSequenceNumber () + SequenceNumber32 (1));
439  }
440  header.SetSourcePort (tcpHeader.GetDestinationPort ());
441  header.SetDestinationPort (tcpHeader.GetSourcePort ());
442  SendPacket (rstPacket, header, dst, src);
444  }
445  else
446  {
448  }
449  }
450  NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
451  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
452  (*endPoints.begin ())->ForwardUp (packet, src, dst, tcpHeader.GetSourcePort ());
453  return IpL4Protocol::RX_OK;
454 }
455 
456 void
458  Ipv4Address saddr, Ipv4Address daddr,
459  uint16_t sport, uint16_t dport, Ptr<NetDevice> oif)
460 {
461  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << oif);
462 
463  TcpHeader tcpHeader;
464  tcpHeader.SetDestinationPort (dport);
465  tcpHeader.SetSourcePort (sport);
466  if(Node::ChecksumEnabled ())
467  {
468  tcpHeader.EnableChecksums ();
469  }
470  tcpHeader.InitializeChecksum (saddr,
471  daddr,
472  PROT_NUMBER);
473  tcpHeader.SetFlags (TcpHeader::ACK);
474  tcpHeader.SetAckNumber (SequenceNumber32 (0));
475 
476  packet->AddHeader (tcpHeader);
477 
478  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
479  if (ipv4 != 0)
480  {
481  Ipv4Header header;
482  header.SetDestination (daddr);
483  header.SetProtocol (PROT_NUMBER);
484  Socket::SocketErrno errno_;
485  Ptr<Ipv4Route> route;
486  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
487  if (ipv4->GetRoutingProtocol () != 0)
488  {
489  route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
490  }
491  else
492  {
493  NS_LOG_ERROR ("No IPV4 Routing Protocol");
494  route = 0;
495  }
496  ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
497  }
498 }
499 
500 void
502  Ipv6Address saddr, Ipv6Address daddr,
503  uint16_t sport, uint16_t dport, Ptr<NetDevice> oif)
504 {
505  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << oif);
506 
507  TcpHeader tcpHeader;
508  tcpHeader.SetDestinationPort (dport);
509  tcpHeader.SetSourcePort (sport);
510  if(Node::ChecksumEnabled ())
511  {
512  tcpHeader.EnableChecksums ();
513  }
514  tcpHeader.InitializeChecksum (saddr,
515  daddr,
516  PROT_NUMBER);
517  tcpHeader.SetFlags (TcpHeader::ACK);
518  tcpHeader.SetAckNumber (SequenceNumber32 (0));
519 
520  packet->AddHeader (tcpHeader);
521 
523  if (ipv6 != 0)
524  {
525  Ipv6Header header;
526  header.SetDestinationAddress (daddr);
527  header.SetNextHeader (PROT_NUMBER);
528  Socket::SocketErrno errno_;
529  Ptr<Ipv6Route> route;
530  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
531  if (ipv6->GetRoutingProtocol () != 0)
532  {
533  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
534  }
535  else
536  {
537  NS_LOG_ERROR ("No IPV6 Routing Protocol");
538  route = 0;
539  }
540  ipv6->Send (packet, saddr, daddr, PROT_NUMBER, route);
541  }
542 }
543 
544 void
546  Ipv4Address saddr, Ipv4Address daddr, Ptr<NetDevice> oif)
547 {
548  NS_LOG_LOGIC ("TcpL4Protocol " << this
549  << " sending seq " << outgoing.GetSequenceNumber ()
550  << " ack " << outgoing.GetAckNumber ()
551  << " flags " << std::hex << (int)outgoing.GetFlags () << std::dec
552  << " data size " << packet->GetSize ());
553  NS_LOG_FUNCTION (this << packet << saddr << daddr << oif);
554  // XXX outgoingHeader cannot be logged
555 
556  TcpHeader outgoingHeader = outgoing;
557  outgoingHeader.SetLength (5); //header length in units of 32bit words
558  /* outgoingHeader.SetUrgentPointer (0); //XXX */
559  if(Node::ChecksumEnabled ())
560  {
561  outgoingHeader.EnableChecksums ();
562  }
563  outgoingHeader.InitializeChecksum (saddr, daddr, PROT_NUMBER);
564 
565  packet->AddHeader (outgoingHeader);
566 
567  Ptr<Ipv4> ipv4 =
568  m_node->GetObject<Ipv4> ();
569  if (ipv4 != 0)
570  {
571  Ipv4Header header;
572  header.SetDestination (daddr);
573  header.SetProtocol (PROT_NUMBER);
574  Socket::SocketErrno errno_;
575  Ptr<Ipv4Route> route;
576  if (ipv4->GetRoutingProtocol () != 0)
577  {
578  route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
579  }
580  else
581  {
582  NS_LOG_ERROR ("No IPV4 Routing Protocol");
583  route = 0;
584  }
585  m_downTarget (packet, saddr, daddr, PROT_NUMBER, route);
586  }
587  else
588  NS_FATAL_ERROR ("Trying to use Tcp on a node without an Ipv4 interface");
589 }
590 
591 void
593  Ipv6Address saddr, Ipv6Address daddr, Ptr<NetDevice> oif)
594 {
595  NS_LOG_LOGIC ("TcpL4Protocol " << this
596  << " sending seq " << outgoing.GetSequenceNumber ()
597  << " ack " << outgoing.GetAckNumber ()
598  << " flags " << std::hex << (int)outgoing.GetFlags () << std::dec
599  << " data size " << packet->GetSize ());
600  NS_LOG_FUNCTION (this << packet << saddr << daddr << oif);
601  // XXX outgoingHeader cannot be logged
602 
603  if (daddr.IsIpv4MappedAddress ())
604  {
605  return (SendPacket (packet, outgoing, saddr.GetIpv4MappedAddress(), daddr.GetIpv4MappedAddress(), oif));
606  }
607  TcpHeader outgoingHeader = outgoing;
608  outgoingHeader.SetLength (5); //header length in units of 32bit words
609  /* outgoingHeader.SetUrgentPointer (0); //XXX */
610  if(Node::ChecksumEnabled ())
611  {
612  outgoingHeader.EnableChecksums ();
613  }
614  outgoingHeader.InitializeChecksum (saddr, daddr, PROT_NUMBER);
615 
616  packet->AddHeader (outgoingHeader);
617 
619  if (ipv6 != 0)
620  {
621  Ipv6Header header;
622  header.SetDestinationAddress (daddr);
623  header.SetSourceAddress (saddr);
624  header.SetNextHeader (PROT_NUMBER);
625  Socket::SocketErrno errno_;
626  Ptr<Ipv6Route> route;
627  if (ipv6->GetRoutingProtocol () != 0)
628  {
629  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
630  }
631  else
632  {
633  NS_LOG_ERROR ("No IPV6 Routing Protocol");
634  route = 0;
635  }
636  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
637  }
638  else
639  NS_FATAL_ERROR ("Trying to use Tcp on a node without an Ipv6 interface");
640 }
641 
642 void
644 {
645  m_downTarget = callback;
646 }
647 
650 {
651  return m_downTarget;
652 }
653 
654 void
656 {
657  m_downTarget6 = callback;
658 }
659 
662 {
663  return m_downTarget6;
664 }
665 
666 } // namespace ns3
667