Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(596)

Side by Side Diff: src/internet-stack/tcp-socket-base.cc

Issue 1702042: New TCP architecture for NS-3
Patch Set: TCP variants: RFC793 (DoD), RFC2001 (Tahoe), RFC2581 (Reno), RFC2582 (NewReno) Created 13 years, 9 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2010 Adrian Sai-wah Tam
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: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
19 */
20
21 #define NS_LOG_APPEND_CONTEXT \
22 if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_n ode->GetId () << "] "; }
23
24 #include "ns3/abort.h"
25 #include "ns3/node.h"
26 #include "ns3/inet-socket-address.h"
27 #include "ns3/log.h"
28 #include "ns3/ipv4.h"
29 #include "ns3/ipv4-interface-address.h"
30 #include "ns3/ipv4-route.h"
31 #include "ns3/ipv4-routing-protocol.h"
32 #include "ns3/simulation-singleton.h"
33 #include "ns3/simulator.h"
34 #include "ns3/packet.h"
35 #include "ns3/uinteger.h"
36 #include "ns3/trace-source-accessor.h"
37 #include "tcp-socket-base.h"
38 #include "tcp-l4-protocol.h"
39 #include "ipv4-end-point.h"
40 #include "tcp-header.h"
41 #include "rtt-estimator.h"
42
43 #include <algorithm>
44
45 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
46
47 namespace ns3 {
48
49 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
50
51 TypeId
52 TcpSocketBase::GetTypeId ()
53 {
54 static TypeId tid = TypeId ("ns3::TcpSocketBase")
55 .SetParent<TcpSocket> ()
56 .AddAttribute ("PersistTimeout",
57 "Persist timeout to probe for rwin",
58 TimeValue (Seconds (6)),
59 MakeTimeAccessor (&TcpSocketBase::m_persistTime),
60 MakeTimeChecker ())
61 ;
62 return tid;
63 }
64
65 TcpSocketBase::TcpSocketBase ()
66 : m_dupAckCount (0),
67 m_delAckCount (0),
68 m_endPoint (0),
69 m_node (0),
70 m_tcp (0),
71 m_rtt (0),
72 m_nextTxSequence (0), // Change this for non-zero initial sequence num ber
73 m_highTxMark (0),
74 m_rxBuffer (0),
75 m_txBuffer (0),
76 m_state (CLOSED),
77 m_errno (ERROR_NOTERROR),
78 m_closeNotified (false),
79 m_closeOnEmpty (false),
80 m_shutdownSend (false),
81 m_shutdownRecv (false),
82 m_connected (false),
83 m_segmentSize (0), // For attribute initialization consistency (qui et valgrind)
84 m_rxWindowSize (0)
85 {
86 NS_LOG_FUNCTION (this);
87 }
88
89 TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
90 : TcpSocket (sock), //copy object::m_tid and socket::callbacks
91 m_dupAckCount (sock.m_dupAckCount),
92 m_delAckCount (0),
93 m_delAckMaxCount (sock.m_delAckMaxCount),
94 m_cnCount (sock.m_cnCount),
95 m_delAckTimeout (sock.m_delAckTimeout),
96 m_persistTime (sock.m_persistTime),
97 m_cnTimeout (sock.m_cnTimeout),
98 m_endPoint (0),
99 m_node (sock.m_node),
100 m_tcp (sock.m_tcp),
101 m_rtt (0),
102 m_nextTxSequence (sock.m_nextTxSequence),
103 m_highTxMark (sock.m_highTxMark),
104 m_rxBuffer (sock.m_rxBuffer),
105 m_txBuffer (sock.m_txBuffer),
106 m_state (sock.m_state),
107 m_errno (sock.m_errno),
108 m_closeNotified (sock.m_closeNotified),
109 m_closeOnEmpty (sock.m_closeOnEmpty),
110 m_shutdownSend (sock.m_shutdownSend),
111 m_shutdownRecv (sock.m_shutdownRecv),
112 m_connected (sock.m_connected),
113 m_segmentSize (sock.m_segmentSize),
114 m_rxWindowSize (sock.m_rxWindowSize)
115 {
116 NS_LOG_FUNCTION (this);
117 NS_LOG_LOGIC ("Invoked the copy constructor");
118 // Copy the rtt estimator if it is set
119 if (sock.m_rtt)
120 {
121 m_rtt = sock.m_rtt->Copy ();
122 }
123 // Reset all callbacks to null
124 Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
125 Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr <Socket>, const Address &> ();
126 Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socke t>, uint32_t> ();
127 SetConnectCallback (vPS, vPS);
128 SetDataSentCallback (vPSUI);
129 SetSendCallback (vPSUI);
130 SetRecvCallback (vPS);
131 }
132
133 TcpSocketBase::~TcpSocketBase ()
134 {
135 NS_LOG_FUNCTION (this);
136 m_node = 0;
137 if (m_endPoint != 0)
138 {
139 NS_ASSERT (m_tcp != 0);
140 /*
141 * Note that this piece of code is seriously convoluted: When we do a
142 * Bind we allocate an Ipv4Endpoint. Immediately thereafter we always do
143 * a FinishBind which sets the DestroyCallback of that endpoint to be
144 * TcpSocketBase::Destroy, below. When m_tcp->DeAllocate is called, it
145 * will in turn call into Ipv4EndpointDemux::DeAllocate with the endpoint
146 * (m_endPoint). The demux will look up the endpoint and destroy it (the
147 * corollary is that we don't own the object pointed to by m_endpoint, we
148 * just borrowed it). The destructor for the endpoint will call the
149 * DestroyCallback which will then invoke TcpSocketBase::Destroy below.
150 * Destroy will zero m_node, m_tcp and m_endpoint. The zero of m_node
151 * and m_tcp need to be here also in case the endpoint is deallocated
152 * before shutdown.
153 */
154 NS_ASSERT (m_endPoint != 0);
155 m_tcp->DeAllocate (m_endPoint);
156 NS_ASSERT (m_endPoint == 0);
157 }
158 m_tcp = 0;
159 CancelAllTimers ();
160 }
161
162 /* Associate a node with this TCP socket */
163 void
164 TcpSocketBase::SetNode (Ptr<Node> node)
165 {
166 m_node = node;
167 }
168
169 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
170 void
171 TcpSocketBase::SetTcp (Ptr<TcpL4Protocol> tcp)
172 {
173 m_tcp = tcp;
174 }
175
176 /* Set an RTT estimator with this socket */
177 void
178 TcpSocketBase::SetRtt (Ptr<RttEstimator> rtt)
179 {
180 m_rtt = rtt;
181 }
182
183 /* From Socket class: Returns error code */
184 enum Socket::SocketErrno
185 TcpSocketBase::GetErrno (void) const
186 {
187 NS_LOG_FUNCTION_NOARGS ();
188 return m_errno;
189 }
190
191 /* From Socket class: Returns associated node */
192 Ptr<Node>
193 TcpSocketBase::GetNode (void) const
194 {
195 NS_LOG_FUNCTION_NOARGS ();
196 return m_node;
197 }
198
199 /* From Socket class: Bind socket to an end-point in TcpL4Protocol */
200 int
201 TcpSocketBase::Bind (void)
202 {
203 NS_LOG_FUNCTION_NOARGS ();
204 m_endPoint = m_tcp->Allocate ();
205 return SetupCallback ();
206 }
207
208 /* From Socket class: Bind socket (with specific address) to an end-point in Tcp L4Protocol */
209 int
210 TcpSocketBase::Bind (const Address &address)
211 {
212 NS_LOG_FUNCTION (this << address);
213 if (!InetSocketAddress::IsMatchingType (address))
214 {
215 m_errno = ERROR_INVAL;
216 return -1;
217 }
218 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
219 Ipv4Address ipv4 = transport.GetIpv4 ();
220 uint16_t port = transport.GetPort ();
221 if (ipv4 == Ipv4Address::GetAny () && port == 0)
222 {
223 m_endPoint = m_tcp->Allocate ();
224 }
225 else if (ipv4 == Ipv4Address::GetAny () && port != 0)
226 {
227 m_endPoint = m_tcp->Allocate (port);
228 }
229 else if (ipv4 != Ipv4Address::GetAny () && port == 0)
230 {
231 m_endPoint = m_tcp->Allocate (ipv4);
232 }
233 else if (ipv4 != Ipv4Address::GetAny () && port != 0)
234 {
235 m_endPoint = m_tcp->Allocate (ipv4, port);
236 }
237 NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
238
239 return SetupCallback ();
240 }
241
242 /* From Socket class: Initiate connection to a remote address:port */
243 int
244 TcpSocketBase::Connect (const Address & address)
245 {
246 NS_LOG_FUNCTION (this << address);
247
248 // If haven't do so, Bind() this socket first
249 if (m_endPoint == 0)
250 {
251 if (Bind () == -1)
252 {
253 NS_ASSERT (m_endPoint == 0);
254 return -1; // Bind() failed
255 }
256 NS_ASSERT (m_endPoint != 0);
257 }
258
259 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
260 m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
261
262 // Get the appropriate local address and port number from the routing protocol and set up endpoint
263 if (SetupEndpoint () != 0)
264 { // Route to destination does not exist
265 return -1;
266 }
267
268 // DoConnect() will do state-checking and send a SYN packet
269 return DoConnect ();
270 }
271
272 /* From Socket class: Listen on the endpoint for an incoming connection */
273 int
274 TcpSocketBase::Listen (void)
275 {
276 NS_LOG_FUNCTION (this);
277 // Linux quits EINVAL if we're not in CLOSED state, so match what they do
278 if (m_state != CLOSED)
279 {
280 m_errno = ERROR_INVAL;
281 return -1;
282 }
283 // In other cases, set the state to LISTEN and done
284 m_state = LISTEN;
285 NS_LOG_LOGIC ("CLOSED -> LISTEN");
286 return 0;
287 }
288
289 /* From Socket class: Kill this socket and signal the peer (if any) */
290 int
291 TcpSocketBase::Close (void)
292 {
293 NS_LOG_FUNCTION (this);
294 // First we check to see if there is any unread rx data
295 // Bug number 426 claims we should send reset in this case.
296 if (m_rxBuffer.Size () != 0)
297 {
298 SendRST ();
299 return 0;
300 }
301 if (m_txBuffer.SizeFromSeq (m_nextTxSequence) > 0)
302 { // App close with pending data must wait until all data transmitted
303 m_closeOnEmpty = true;
304 NS_LOG_LOGIC ("Socket " << this << " deferring close, state " << m_state);
305 return 0;
306 }
307 return DoClose ();
308 }
309
310 /* From Socket class: Signal a termination of send */
311 int
312 TcpSocketBase::ShutdownSend (void)
313 {
314 NS_LOG_FUNCTION (this);
315 m_shutdownSend = true;
316 return 0;
317 }
318
319 /* From Socket class: Signal a termination of receive */
320 int
321 TcpSocketBase::ShutdownRecv (void)
322 {
323 NS_LOG_FUNCTION (this);
324 m_shutdownRecv = true;
325 return 0;
326 }
327
328 /* From Socket class: Send a packet. Parameter flags is not used. Packet has no
329 TCP header. Invoked by upper-layer application */
330 int
331 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
332 {
333 NS_LOG_FUNCTION (this << p);
334 if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
335 {
336 // Store the packet into Tx buffer
337 if (!m_txBuffer.Add (p))
338 { // TxBuffer overflow, send failed
339 m_errno = ERROR_MSGSIZE;
340 return -1;
341 }
342 // Submit the data to lower layers
343 NS_LOG_DEBUG ("txBufSize=" << m_txBuffer.Size () << " state " << m_state);
344 if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
345 { // Try to send the data out
346 SendPendingData (m_connected);
347 }
348 return p->GetSize ();
349 }
350 else
351 { // Connection not established yet
352 m_errno = ERROR_NOTCONN;
353 return -1; // Send failure
354 }
355 }
356
357 /* From Socket class: In TcpSocketBase, it is same as Send() call */
358 int
359 TcpSocketBase::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
360 {
361 return Send (p, flags); // SendTo() and Send() are the same
362 }
363
364 /* From Socket class: Return data to upper-layer application. Parameter flags
365 is not used. Data is returned as a packet of size no larger than maxSize */
366 Ptr<Packet>
367 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
368 {
369 NS_LOG_FUNCTION (this);
370 if (m_rxBuffer.Size () == 0 && m_state == CLOSE_WAIT)
371 {
372 return Create<Packet> (); // Send EOF on connection close
373 }
374 Ptr<Packet> outPacket = m_rxBuffer.Extract (maxSize);
375 if (outPacket != 0 && outPacket->GetSize () != 0)
376 {
377 SocketAddressTag tag;
378 tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoi nt->GetPeerPort ()));
379 outPacket->AddPacketTag (tag);
380 }
381 return outPacket;
382 }
383
384 /* From Socket class: Recv and return the remote's address */
385 Ptr<Packet>
386 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
387 {
388 NS_LOG_FUNCTION (this << maxSize << flags);
389 Ptr<Packet> packet = Recv (maxSize, flags);
390 // Null packet means no data to read, and an empty packet indicates EOF
391 if (packet != 0 && packet->GetSize () != 0)
392 {
393 GetSockName (fromAddress);
394 }
395 return packet;
396 }
397
398 /* From Socket class: Get the max number of bytes an app can send */
399 uint32_t
400 TcpSocketBase::GetTxAvailable (void) const
401 {
402 NS_LOG_FUNCTION (this);
403 return m_txBuffer.Available ();
404 }
405
406 /* From Socket class: Get the max number of bytes an app can read */
407 uint32_t
408 TcpSocketBase::GetRxAvailable (void) const
409 {
410 NS_LOG_FUNCTION (this);
411 return m_rxBuffer.Available ();
412 }
413
414 /* From Socket class: Return local address:port */
415 int
416 TcpSocketBase::GetSockName (Address &address) const
417 {
418 NS_LOG_FUNCTION (this);
419 if (m_endPoint != 0)
420 {
421 address = InetSocketAddress (m_endPoint->GetLocalAddress (), m_endPoint->G etLocalPort ());
422 }
423 else
424 { // It is possible to call this method on a socket without a name
425 // in which case, behavior is unspecified
426 address = InetSocketAddress (Ipv4Address::GetZero (), 0);
427 }
428 return 0;
429 }
430
431 /* From Socket class: Bind this socket to the specified NetDevice */
432 void
433 TcpSocketBase::BindToNetDevice (Ptr<NetDevice> netdevice)
434 {
435 NS_LOG_FUNCTION (netdevice);
436 Socket::BindToNetDevice (netdevice); // Includes sanity check
437 if (m_endPoint == 0)
438 {
439 if (Bind () == -1)
440 {
441 NS_ASSERT (m_endPoint == 0);
442 return;
443 }
444 NS_ASSERT (m_endPoint != 0);
445 }
446 m_endPoint->BindToNetDevice (netdevice);
447 return;
448 }
449
450 /* Clean up. Set up callback functions in the end-point. */
451 int
452 TcpSocketBase::SetupCallback (void)
453 {
454 NS_LOG_FUNCTION (this);
455 if (m_endPoint == 0)
456 {
457 return -1;
458 }
459 m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSoc ketBase> (this)));
460 m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<Tcp SocketBase> (this)));
461 return 0;
462 }
463
464 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
465 int
466 TcpSocketBase::DoConnect (void)
467 {
468 NS_LOG_FUNCTION (this);
469
470 // A new connection is allowed only if this socket does not have a connection
471 if (m_state == CLOSED || m_state == LISTEN || m_state == SYN_SENT || m_state = = LAST_ACK || m_state == CLOSE_WAIT)
472 { // send a SYN packet and change state into SYN_SENT
473 SendEmptyPacket (TcpHeader::SYN);
474 m_state = SYN_SENT;
475 NS_LOG_LOGIC ("moved to SYN_SENT state");
476 }
477 else if (m_state != TIME_WAIT)
478 { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, a n connection
479 // exists. We send RST, tear down everything, and close this socket.
480 CloseAndNotify ();
481 SendRST ();
482 }
483 return 0;
484 }
485
486 /* Do the action to close the socket. Usually send a packet with appropriate
487 flags depended on the current m_state. */
488 int
489 TcpSocketBase::DoClose (void)
490 {
491 NS_LOG_FUNCTION (this);
492 switch (m_state)
493 {
494 case SYN_RCVD:
495 case ESTABLISHED:
496 // send FIN to close the peer
497 SendEmptyPacket (TcpHeader::FIN);
498 m_state = FIN_WAIT_1;
499 NS_LOG_LOGIC ("ESTABLISHED -> FIN_WAIT_1");
500 break;
501 case CLOSE_WAIT:
502 // send FIN+ACK to close the peer
503 SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
504 m_state = LAST_ACK;
505 NS_LOG_LOGIC ("CLOSE_WAIT -> LAST_ACK");
506 break;
507 case SYN_SENT:
508 case CLOSING:
509 // Send RST if application closes in SYN_SENT and CLOSING
510 CloseAndNotify ();
511 SendRST ();
512 break;
513 case LISTEN:
514 case LAST_ACK:
515 // In these three states, move to CLOSED and tear down the end point
516 CloseAndNotify ();
517 break;
518 case CLOSED:
519 case FIN_WAIT_1:
520 case FIN_WAIT_2:
521 case TIME_WAIT:
522 default: /* mute compiler */
523 // Do nothing in these four states
524 break;
525 }
526 return 0;
527 }
528
529 /* Peacefully close the socket by notifying the upper layer and deallocate end p oint */
530 void
531 TcpSocketBase::CloseAndNotify (void)
532 {
533 NS_LOG_FUNCTION (this);
534
535 if (!m_closeNotified) NotifyNormalClose ();
536 m_closeNotified = true;
537 m_state = CLOSED;
538 DeallocateEndPoint ();
539 NS_LOG_LOGIC ("moved to CLOSED state");
540 }
541
542 /* Function called by the L3 protocol when it received a packet to pass on to
543 the TCP. This function is registered as the "RxCallback" function in
544 SetupCallback(), which invoked by Bind(), and CompleteFork() */
545 void
546 TcpSocketBase::ForwardUp (Ptr<Packet> packet, Ipv4Address saddr, Ipv4Address dad dr, uint16_t port)
547 {
548 NS_LOG_FUNCTION (this << packet << saddr << daddr << port);
549 NS_LOG_DEBUG ("Socket " << this << " got forward up" <<
550 " saddr " << m_endPoint->GetPeerAddress () <<
551 " sport " << m_endPoint->GetPeerPort () <<
552 " daddr " << m_endPoint->GetLocalAddress () <<
553 " dport " << m_endPoint->GetLocalPort ());
554 Address fromAddress = InetSocketAddress (saddr, port);
555 Address toAddress = InetSocketAddress (daddr, m_endPoint->GetLocalPort ());
556
557 // Peel off TCP header, and look for ACK flag
558 TcpHeader tcpHeader;
559 packet->RemoveHeader (tcpHeader);
560 if (tcpHeader.GetFlags () & TcpHeader::ACK)
561 { // TODO: This RTT function shall be changed to handle timestamp options
562 // One solution is to pass the whole header instead of just the number
563 m_rtt->AckSeq (tcpHeader.GetAckNumber () );
564 }
565
566 // Update Rx window size, i.e. the flow control window
567 if (m_rxWindowSize == 0 && tcpHeader.GetWindowSize () != 0)
568 { // persist probes end
569 NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
570 m_persistEvent.Cancel ();
571 }
572 m_rxWindowSize = tcpHeader.GetWindowSize ();
573
574 // TCP state machine code in different process functions
575 // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
576 switch (m_state)
577 {
578 case ESTABLISHED:
579 ProcessEstablished (packet, tcpHeader);
580 break;
581 case LISTEN:
582 ProcessListen (packet, tcpHeader, fromAddress, toAddress);
583 break;
584 case TIME_WAIT:
585 // Do nothing
586 break;
587 case CLOSED:
588 // Send RST if the incoming packet is not a RST
589 if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHea der::RST)
590 {
591 SendRST ();
592 }
593 break;
594 case SYN_SENT:
595 ProcessSynSent (packet, tcpHeader);
596 break;
597 case SYN_RCVD:
598 ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
599 break;
600 case FIN_WAIT_1:
601 case FIN_WAIT_2:
602 case CLOSE_WAIT:
603 ProcessWait (packet, tcpHeader);
604 break;
605 case CLOSING:
606 ProcessClosing (packet, tcpHeader);
607 break;
608 case LAST_ACK:
609 ProcessLastAck (packet, tcpHeader);
610 break;
611 default: // mute compiler
612 break;
613 }
614 }
615
616 /* Received a packet upon ESTABLISHED state. This function is mimicking the
617 role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
618 void
619 TcpSocketBase::ProcessEstablished (Ptr<Packet> packet, const TcpHeader& tcpHeade r)
620 {
621 NS_LOG_FUNCTION (this << tcpHeader);
622
623 // Extract the flags. PSH and URG are not honoured.
624 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
625
626 // Different flags are different events
627 if (tcpflags == TcpHeader::ACK)
628 {
629 ReceivedAck (packet, tcpHeader);
630 }
631 else if (tcpflags == TcpHeader::SYN)
632 { // Received SYN, set state to SYN_RCVD and respond with a SYN+ACK
633 m_state = SYN_RCVD;
634 NS_LOG_LOGIC ("ESTABLISHED -> SYN_RCVD");
635 m_rxBuffer.SetNextRxSeq (tcpHeader.GetSequenceNumber () + SequenceNumber ( 1));
636 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
637 // TODO: Isn't it illegal to get a SYN if it is already ESTABLISHED?
638 }
639 else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
640 { // No action for received SYN+ACK, it is probably a duplicated packet
641 }
642 else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader ::ACK))
643 { // Received FIN or FIN+ACK, bring down this socket nicely
644 PeerClose (packet, tcpHeader);
645 if (m_rxBuffer.Finished ())
646 {
647 m_state = CLOSE_WAIT;
648 NS_LOG_LOGIC ("ESTABLISHED -> CLOSE_WAIT");
649 }
650 }
651 else if (tcpflags == 0)
652 { // No flags means there is only data
653 ReceivedData (packet, tcpHeader);
Adrian 2010/06/25 08:46:10 Function name change: NewRx->ReceivedData
654 if (m_rxBuffer.Finished ())
655 {
656 m_state = CLOSE_WAIT;
657 NS_LOG_LOGIC ("ESTABLISHED -> CLOSE_WAIT");
658 PeerClose (packet, tcpHeader);
659 }
660 }
661 else if (m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
662 { // Received RST or the TCP flags is invalid, in either case, terminate thi s socket
663 CloseAndNotify ();
664 if (tcpflags != TcpHeader::RST)
665 { // this must be an invalid flag, send reset
666 SendRST ();
667 }
668 }
669 }
670
671 /* Process the newly received ACK */
672 void
673 TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
674 {
675 NS_LOG_FUNCTION (this << tcpHeader);
676
677 // Received ACK. Compare the ACK number against highest unacked seqno
678 if (tcpHeader.GetAckNumber () < m_txBuffer.HeadSeq ())
679 { // Case 1: Old ACK, ignored.
680 }
681 else if (tcpHeader.GetAckNumber () == m_txBuffer.HeadSeq ())
682 { // Case 2: Potentially a duplicated ACK
683 if (tcpHeader.GetAckNumber () < m_nextTxSequence)
684 {
685 DupAck (tcpHeader, ++m_dupAckCount);
686 }
687 // otherwise, the ACK is precisely equal to the nextTxSequence
688 NS_ASSERT (tcpHeader.GetAckNumber () <= m_nextTxSequence);
689 }
690 else if (tcpHeader.GetAckNumber () > m_txBuffer.HeadSeq ())
691 { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer
692 NewAck (tcpHeader.GetAckNumber ());
693 m_dupAckCount = 0;
694 }
695 // If there is any data piggybacked, store it into m_rxBuffer
696 if (packet->GetSize () > 0)
697 {
698 ReceivedData (packet, tcpHeader);
699 }
700 }
701
702 /* Received a packet upon LISTEN state. */
703 void
704 TcpSocketBase::ProcessListen (Ptr<Packet> packet, const TcpHeader& tcpHeader,
705 const Address& fromAddress, const Address& toAddre ss)
706 {
707 NS_LOG_FUNCTION (this << tcpHeader);
708
709 // Extract the flags. PSH and URG are not honoured.
710 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
711
712 // Fork a socket if received a SYN. Do nothing otherwise.
713 // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
714 if (tcpflags != TcpHeader::SYN) return;
715
716 // Call socket's notify function to let the server app know we got a SYN
717 // If the server app refuses the connection, do nothing
718 if (!NotifyConnectionRequest (fromAddress)) return;
719 // Clone the socket, simulate fork
720 Ptr<TcpSocketBase> newSock = Fork ();
721 NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
722 Simulator::ScheduleNow (&TcpSocketBase::CompleteFork, newSock,
723 packet, tcpHeader, fromAddress, toAddress);
724 }
725
726 /* Received a packet upon SYN_SENT */
727 void
728 TcpSocketBase::ProcessSynSent (Ptr<Packet> packet, const TcpHeader& tcpHeader)
729 {
730 NS_LOG_FUNCTION (this << tcpHeader);
731
732 // Extract the flags. PSH and URG are not honoured.
733 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
734
735 if (tcpflags == 0)
736 { // Bare data, accept it and move to ESTABLISHED state. This is not a norma l behaviour. Remove this?
737 m_state = ESTABLISHED;
738 m_connected = true;
739 ReceivedData (packet, tcpHeader);
740 Simulator::ScheduleNow (&TcpSocketBase::ConnectionSucceeded, this);
741 NS_LOG_LOGIC ("SYN_SENT -> ESTABLISHED");
742 }
743 else if (tcpflags == TcpHeader::ACK)
744 { // Ignore ACK in SYN_SENT
745 }
746 else if (tcpflags == TcpHeader::SYN)
747 { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
748 m_state = SYN_RCVD;
749 m_rxBuffer.SetNextRxSeq (tcpHeader.GetSequenceNumber () + SequenceNumber ( 1));
750 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
751 NS_LOG_LOGIC ("SYN_SENT -> SYN_RCVD");
752 }
753 else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK)
754 && m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
755 { // Handshake completed
756 m_state = ESTABLISHED;
757 m_connected = true;
758 m_rxBuffer.SetNextRxSeq (tcpHeader.GetSequenceNumber () + SequenceNumber ( 1));
759 m_nextTxSequence = tcpHeader.GetAckNumber ();
760 m_txBuffer.SetHeadSeq (m_nextTxSequence);
761 SendEmptyPacket (TcpHeader::ACK);
762 if (GetTxAvailable () > 0)
763 {
764 NotifySend (GetTxAvailable ());
765 }
766 SendPendingData (m_connected);
767 Simulator::ScheduleNow (&TcpSocketBase::ConnectionSucceeded, this);
768 NS_LOG_LOGIC ("SYN_SENT -> ESTABLISHED");
769 }
770 else if (m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
771 { // Other in-sequence input
772 CloseAndNotify ();
773 if (tcpflags != TcpHeader::RST)
774 { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
775 SendRST ();
776 }
777 }
778 }
779
780 /* Received a packet upon SYN_RCVD */
781 void
782 TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader,
783 const Address& fromAddress, const Address& toAddr ess)
784 {
785 NS_LOG_FUNCTION (this << tcpHeader);
786
787 // Extract the flags. PSH and URG are not honoured.
788 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
789
790 if (tcpflags == 0)
791 { // Bare data, accept it and move to ESTABLISHED state. This is not a norma l behaviour.
792 m_endPoint->SetPeer (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPor t ());
793 NotifyNewConnectionCreated (this, fromAddress);
794 m_state = ESTABLISHED;
795 m_connected = true;
796 #if 0
797 // Always respond to first data packet to speed up the connection.
798 // Remove to get the behaviour of old NS-3 code.
799 m_delAckCount = m_delAckMaxCount;
800 #endif
801 ReceivedData (packet, tcpHeader);
802 NS_LOG_LOGIC ("SYN_RCVD -> ESTABLISHED");
803 }
804 else if (tcpflags == TcpHeader::ACK
805 && m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
806 { // Handshake completed.
807 m_state = ESTABLISHED;
808 m_connected = true;
809 m_endPoint->SetPeer (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPor t ());
810 #if 0
811 // Always respond to first data packet to speed up the connection.
812 // Remove to get the behaviour of old NS-3 code.
813 m_delAckCount = m_delAckMaxCount;
814 #endif
815 ReceivedAck (packet, tcpHeader);
Adrian 2010/06/25 08:46:10 This was NewAck but now replaced with ReceivedAck
816 NotifyNewConnectionCreated (this, fromAddress);
817 NS_LOG_LOGIC ("SYN_RCVD -> ESTABLISHED");
818 }
819 else if (tcpflags == TcpHeader::SYN)
820 { // Probably the peer lost my SYN+ACK
821 m_rxBuffer.SetNextRxSeq (tcpHeader.GetSequenceNumber () + SequenceNumber ( 1));
822 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
823 }
824 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
825 {
826 PeerClose (packet, tcpHeader);
827 if (m_rxBuffer.Finished ())
828 {
829 m_state = CLOSE_WAIT;
830 NS_LOG_LOGIC ("SYN_RCVD -> CLOSE_WAIT");
831 }
832 }
833 else if (m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
834 { // Other in-sequence input
835 CloseAndNotify ();
836 if (tcpflags != TcpHeader::RST)
837 { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
838 SendRST ();
839 }
840 }
841 }
842
843 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
844 void
845 TcpSocketBase::ProcessWait (Ptr<Packet> packet, const TcpHeader& tcpHeader)
846 {
847 NS_LOG_FUNCTION (this << tcpHeader);
848
849 // Extract the flags. PSH and URG are not honoured.
850 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
851
852 if (tcpflags == 0)
853 { // Bare data, accept it
854 ReceivedData (packet, tcpHeader);
855 }
856 else if (tcpflags == TcpHeader::ACK)
857 { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
858 ReceivedAck (packet, tcpHeader);
859 if (m_state == FIN_WAIT_1 && tcpHeader.GetSequenceNumber () == m_rxBuffer. NextRxSeq ())
860 { // This ACK corresponds to the FIN sent
861 m_state = FIN_WAIT_2;
862 NS_LOG_LOGIC ("FIN_WAIT_1 -> FIN_WAIT_2");
863 }
864 }
865 else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader ::ACK))
866 { // Got FIN, respond with ACK and move to next state
867 m_rxBuffer.SetFinSeq (tcpHeader.GetSequenceNumber ());
868 if (m_rxBuffer.Finished ())
869 { // Action only if the FIN received is in-sequence
870 SendEmptyPacket (TcpHeader::ACK);
871 if (m_state == FIN_WAIT_1 && tcpflags == TcpHeader::FIN)
872 {
873 m_state = CLOSING;
874 if (!m_shutdownRecv) NotifyDataRecv ();
875 NS_LOG_LOGIC ("FIN_WAIT_1 -> CLOSING");
876 }
877 else if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2)
878 {
879 m_state = TIME_WAIT;
880 if (!m_shutdownRecv) NotifyDataRecv ();
881 NS_LOG_LOGIC ("moved to TIME_WAIT state");
882 // TODO: In TIME_WAIT, we supposed to move to CLOSED after 2*MSL t ime
883 // but this move is not yet implemeneted. Is this necessary?
884 }
885 }
886 }
887 else if (m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
888 { // This is a SYN or SYN+ACK or RST or bad flags
889 CloseAndNotify ();
890 if (tcpflags != TcpHeader::RST)
891 {
892 SendRST ();
893 }
894 }
895 }
896
897 /* Received a packet upon CLOSING */
898 void
899 TcpSocketBase::ProcessClosing (Ptr<Packet> packet, const TcpHeader& tcpHeader)
900 {
901 NS_LOG_FUNCTION (this << tcpHeader);
902
903 // Extract the flags. PSH and URG are not honoured.
904 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
905
906 if (tcpflags == TcpHeader::ACK)
907 {
908 if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSeq ())
909 { // This ACK corresponds to the FIN sent
910 m_state = TIME_WAIT;
911 NS_LOG_LOGIC ("CLOSING -> TIME_WAIT");
912 // TODO: In TIME_WAIT, we supposed to move to CLOSED after 2*MSL time
913 // but this move is not yet implemeneted. Is this necessary?
914 }
915 }
916 else if (m_rxBuffer.NextRxSeq () == tcpHeader.GetSequenceNumber ())
917 {
918 CloseAndNotify ();
919 if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader: :ACK))
920 { // FIN from the peer as well. We can close immediately.
921 SendEmptyPacket (TcpHeader::ACK);
922 }
923 else if (tcpflags != TcpHeader::RST)
924 { // Receive of SYN or SYN+ACK or bad flags or pure data
925 SendRST ();
926 }
927 }
928 }
929
930 /* Received a packet upon LAST_ACK */
931 void
932 TcpSocketBase::ProcessLastAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
933 {
934 NS_LOG_FUNCTION (this << tcpHeader);
935
936 // Extract the flags. PSH and URG are not honoured.
937 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
938
939 if (tcpflags == 0)
940 {
941 ReceivedData (packet, tcpHeader);
942 }
943 else if (tcpflags == TcpHeader::ACK)
944 {
945 if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSeq ())
946 { // This ACK corresponds to the FIN sent. This socket closed peacefully .
947 CloseAndNotify ();
948 }
949 }
950 else if (tcpflags == TcpHeader::FIN)
951 { // Received FIN again, the peer probably lost the FIN+ACK
952 SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
953 }
954 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeade r::RST)
955 {
956 CloseAndNotify ();
957 }
958 else
959 { // Received a SYN or SYN+ACK or bad flags
960 CloseAndNotify ();
961 SendRST ();
962 }
963 }
964
965 /* Peer sent me a FIN. Close down this socket. */
966 void
967 TcpSocketBase::PeerClose (Ptr<Packet> p, const TcpHeader& tcpHeader)
968 {
969 NS_LOG_FUNCTION (this << tcpHeader);
970
971 // If FIN is out of sequence, remember it and process new sequence rx
972 if (tcpHeader.GetSequenceNumber () != m_rxBuffer.NextRxSeq ())
973 {
974 if (tcpHeader.GetSequenceNumber () > m_rxBuffer.NextRxSeq ())
975 {
976 m_rxBuffer.SetFinSeq (tcpHeader.GetSequenceNumber () + SequenceNumber (p->GetSize ()));
Adrian 2010/06/25 08:46:10 In case FIN piggybacked with data, the correct FIN
977 NS_LOG_LOGIC ("TcpSocketBase " << this << " accpeted FIN at rxseq" <<
978 tcpHeader.GetSequenceNumber () <<
979 " nextRxSeq " << m_rxBuffer.NextRxSeq ());
980 ReceivedData (p, tcpHeader);
981 }
982 return;
983 }
984 // If FIN is in sequence with new data, call ReceivedData
985 if (tcpHeader.GetSequenceNumber () + SequenceNumber (p->GetSize ()) > m_rxBuff er.NextRxSeq ())
986 {
987 ReceivedData (p, tcpHeader);
988 // This is the old NS-3 behaviour that if a FIN is piggybacked with data,
989 // the data and the FIN are ACKed separately. RFC didn't require this.
990 SendEmptyPacket (TcpHeader::ACK);
991 }
992 // For all in-sequence FIN, close the socket immediately
993 m_rxBuffer.SetFinSeq (tcpHeader.GetSequenceNumber () + SequenceNumber (p->GetS ize ()));
994 States_t saveState = m_state; // Used to see if app responds
995 NS_LOG_LOGIC ("TcpSocketBase " << this << " peer close, state " << m_state);
996 if (!m_closeNotified)
997 {
998 NS_LOG_LOGIC ("TCP " << this << " calling AppCloseRequest");
999 if (!m_closeNotified) NotifyNormalClose ();
1000 m_closeNotified = true;
1001 }
1002 NS_LOG_LOGIC ("TcpSocketBase " << this << " peer close, state after " << m_sta te);
1003 if (m_state == saveState)
1004 { // Need to ack, the application will close later
1005 SendEmptyPacket (TcpHeader::ACK);
1006 }
1007 if (m_state == LAST_ACK)
1008 {
1009 NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
1010 m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
1011 &TcpSocketBase::LastAckTimeout, this );
1012 }
1013 }
1014
1015 /* Kill this socket. This is a callback function configured to m_endpoint in
1016 SetupCallback(), invoked when the endpoint is destroyed. */
1017 void
1018 TcpSocketBase::Destroy (void)
1019 {
1020 NS_LOG_FUNCTION (this);
1021 m_node = 0;
1022 m_endPoint = 0;
1023 m_tcp = 0;
1024 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1025 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetS econds ());
1026 CancelAllTimers ();
1027 }
1028
1029 /* Send an empty packet with specified TCP flags */
1030 void
1031 TcpSocketBase::SendEmptyPacket (uint8_t flags)
1032 {
1033 NS_LOG_FUNCTION (this << (uint32_t)flags);
1034 Ptr<Packet> p = Create<Packet> ();
1035 TcpHeader header;
1036
1037 if (m_endPoint == 0)
1038 {
1039 NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
1040 return;
1041 }
1042 if (flags & TcpHeader::FIN)
1043 {
1044 flags |= TcpHeader::ACK;
1045 }
1046
1047 header.SetFlags (flags);
1048 header.SetSequenceNumber (m_nextTxSequence);
1049 header.SetAckNumber (m_rxBuffer.NextRxSeq ());
1050 header.SetSourcePort (m_endPoint->GetLocalPort ());
1051 header.SetDestinationPort (m_endPoint->GetPeerPort ());
1052 header.SetWindowSize (AdvertisedWindowSize ());
1053 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), m_endPoint->GetP eerAddress (), m_boundnetdevice);
1054 Time rto = m_rtt->RetransmitTimeout ();
1055 bool hasSyn = flags & TcpHeader::SYN;
1056 bool hasFin = flags & TcpHeader::FIN;
1057 bool isAck = flags == TcpHeader::ACK;
1058 if (hasSyn)
1059 { // Exponential backoff of connection time out
1060 rto = m_cnTimeout;
1061 m_cnTimeout = m_cnTimeout + m_cnTimeout;
1062 m_cnCount--;
1063 }
1064 if (flags & TcpHeader::ACK)
1065 { // If sending an ACK, cancel the delay ACK as well
1066 m_delAckEvent.Cancel ();
1067 m_delAckCount = 0;
1068 }
1069 if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
1070 { // Setup ReTx timer if not have one at the moment
1071 NS_LOG_LOGIC ("Schedule retransmission timeout at time "
1072 << Simulator::Now ().GetSeconds () << " to expire at time "
1073 << (Simulator::Now () + rto).GetSeconds ());
1074 m_retxEvent = Simulator::Schedule (rto, &TcpSocketBase::ReTxTimeout, this) ;
1075 }
1076 }
1077
1078 /* This function closes the endpoint completely. Called upon RST_TX action. */
1079 void
1080 TcpSocketBase::SendRST (void)
1081 {
1082 NS_LOG_FUNCTION (this);
1083 SendEmptyPacket (TcpHeader::RST);
1084 NotifyErrorClose ();
1085 DeallocateEndPoint ();
1086 }
1087
1088 /* Deallocate the end point the cancel all the timers */
1089 void
1090 TcpSocketBase::DeallocateEndPoint (void)
1091 {
1092 if (m_endPoint != 0)
1093 {
1094 m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
1095 m_tcp->DeAllocate (m_endPoint);
1096 m_endPoint = 0;
1097 CancelAllTimers ();
1098 }
1099 }
1100
1101 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn 't specify one. */
1102 int
1103 TcpSocketBase::SetupEndpoint ()
1104 {
1105 NS_LOG_FUNCTION (this);
1106 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
1107 NS_ASSERT (ipv4 != 0);
1108 if (ipv4->GetRoutingProtocol () == 0)
1109 {
1110 NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
1111 }
1112 // Create a dummy packet, then ask the routing function for the best output
1113 // interface's address
1114 Ipv4Header header;
1115 header.SetDestination (m_endPoint->GetPeerAddress ());
1116 Socket::SocketErrno errno_;
1117 Ptr<Ipv4Route> route;
1118 Ptr<NetDevice> oif = m_boundnetdevice;
1119 route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
1120 if (route == 0)
1121 {
1122 NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not e xist");
1123 NS_LOG_ERROR (errno_);
1124 m_errno = errno_;
1125 return -1;
1126 }
1127 NS_LOG_LOGIC ("Route exists");
1128 m_endPoint->SetLocalAddress (route->GetSource ());
1129 return 0;
1130 }
1131
1132 /* This function is called only if a SYN received in LISTEN state. After
1133 TcpSocketBase cloned, allocate a new end point to handle the incoming
1134 connection and send a SYN+ACK to complete the handshake. */
1135 void
1136 TcpSocketBase::CompleteFork (Ptr<Packet> p, const TcpHeader& h,
1137 const Address& fromAddress, const Address& toAddres s)
1138 {
1139 // Get port and address from peer (connecting host)
1140 m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIp v4 (),
1141 InetSocketAddress::ConvertFrom (toAddress).GetPo rt (),
1142 InetSocketAddress::ConvertFrom (fromAddress).Get Ipv4 (),
1143 InetSocketAddress::ConvertFrom (fromAddress).Get Port ());
1144
1145 // Change the cloned socket from LISTEN state to SYN_RCVD
1146 m_state = SYN_RCVD;
1147 NS_LOG_LOGIC ("LISTEN -> SYN_RCVD");
1148 // Setup callback and call ProcessPacketAction to continue the handshake
1149 SetupCallback ();
1150 // Set the sequence number and send SYN+ACK
1151 m_rxBuffer.SetNextRxSeq (h.GetSequenceNumber () + SequenceNumber (1));
1152 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
1153 }
1154
1155 void
1156 TcpSocketBase::ConnectionSucceeded ()
1157 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
1158 // be called as a scheduled event
1159 NotifyConnectionSucceeded ();
1160 }
1161
1162 // Send as much pending data as possible according to the Tx window. Note that
1163 // this function did not implement the PSH flag
1164 bool
1165 TcpSocketBase::SendPendingData (bool withAck)
1166 {
1167 NS_LOG_FUNCTION (this << withAck);
1168 if (m_txBuffer.Size () == 0) return false; // Nothing to send
1169 if (m_endPoint == 0)
1170 {
1171 NS_LOG_INFO ("TcpSocketImpl::SendPendingData: No endpoint; m_shutdownSend= " << m_shutdownSend);
1172 return false; // Is this the right way to handle this condition?
1173 }
1174 uint32_t nPacketsSent = 0;
1175 while (m_txBuffer.SizeFromSeq (m_nextTxSequence))
1176 {
1177 uint32_t w = AvailableWindow (); // Get available window size
1178 NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
1179 " w " << w <<
1180 " rxwin " << m_rxWindowSize <<
1181 " segsize " << m_segmentSize <<
1182 " nextTxSeq " << m_nextTxSequence <<
1183 " highestRxAck " << m_txBuffer.HeadSeq () <<
1184 " pd->Size " << m_txBuffer.Size () <<
1185 " pd->SFS " << m_txBuffer.SizeFromSeq (m_nextTxSequence));
1186 // Quit if send disallowed
1187 if (m_shutdownSend)
1188 {
1189 m_errno = ERROR_SHUTDOWN;
1190 return false;
1191 }
1192 // Stop sending if we need to wait for a larger Tx window
1193 if (w < m_segmentSize && m_txBuffer.SizeFromSeq (m_nextTxSequence) > w)
1194 {
1195 break; // No more
1196 }
1197 uint32_t s = std::min (w, m_segmentSize); // Send no more than window
1198 Ptr<Packet> p = m_txBuffer.CopyFromSeq (s, m_nextTxSequence);
1199 NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
1200 " txseq " << m_nextTxSequence <<
1201 " s " << s << " datasize " << p->GetSize ());
1202 uint8_t flags = 0;
1203 uint32_t sz = p->GetSize (); // Size of packet
1204 uint32_t remainingData = m_txBuffer.SizeFromSeq (m_nextTxSequence + Sequen ceNumber (sz));
1205 if (m_closeOnEmpty && (remainingData == 0))
1206 {
1207 flags = TcpHeader::FIN;
1208 m_state = FIN_WAIT_1;
1209 NS_LOG_LOGIC ("moved to FIN_WAIT_1 state");
1210 }
1211 if (withAck)
1212 {
1213 flags |= TcpHeader::ACK;
1214 }
1215 TcpHeader header;
1216 header.SetFlags (flags);
1217 header.SetSequenceNumber (m_nextTxSequence);
1218 header.SetAckNumber (m_rxBuffer.NextRxSeq ());
1219 header.SetSourcePort (m_endPoint->GetLocalPort ());
1220 header.SetDestinationPort (m_endPoint->GetPeerPort ());
1221 header.SetWindowSize (AdvertisedWindowSize ());
1222 if (m_retxEvent.IsExpired () )
1223 { // Schedule retransmit
1224 Time rto = m_rtt->RetransmitTimeout ();
1225 NS_LOG_LOGIC (this << " SendPendingData Schedule ReTxTimeout at time " <<
1226 Simulator::Now ().GetSeconds () << " to expire at time " <<
1227 (Simulator::Now () + rto).GetSeconds () );
1228 m_retxEvent = Simulator::Schedule (rto, &TcpSocketBase::ReTxTimeout, t his);
1229 }
1230 NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
1231 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
1232 m_endPoint->GetPeerAddress (), m_boundnetdevice);
1233 m_rtt->SentSeq (m_nextTxSequence, sz); // notify the RTT
1234 // Notify the application of the data being sent
1235 Simulator::ScheduleNow (&TcpSocketBase::NotifyDataSent, this, sz);
1236 nPacketsSent++; // Count sent this loop
1237 m_nextTxSequence += sz; // Advance next tx sequence
1238 // Update highTxMark
1239 m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
1240 }
1241 NS_LOG_LOGIC ("SendPendingData Sent " << nPacketsSent << " packets");
1242 NS_LOG_LOGIC ("RETURN SendPendingData");
1243 return (nPacketsSent > 0);
1244 }
1245
1246 uint32_t
1247 TcpSocketBase::UnAckDataCount ()
1248 {
1249 NS_LOG_FUNCTION (this);
1250 return m_nextTxSequence - m_txBuffer.HeadSeq ();
1251 }
1252
1253 uint32_t
1254 TcpSocketBase::BytesInFlight ()
1255 {
1256 NS_LOG_FUNCTION (this);
1257 return m_highTxMark - m_txBuffer.HeadSeq ();
1258 }
1259
1260 uint32_t
1261 TcpSocketBase::Window ()
1262 {
1263 NS_LOG_FUNCTION (this);
1264 return m_rxWindowSize;
1265 }
1266
1267 uint32_t
1268 TcpSocketBase::AvailableWindow ()
1269 {
1270 NS_LOG_FUNCTION_NOARGS ();
1271 uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
1272 uint32_t win = Window (); // Number of bytes allowed to be outstanding
1273 NS_LOG_LOGIC ("UnAckCount=" << unack << ", Win=" << win);
1274 return (win < unack) ? 0 : (win - unack);
1275 }
1276
1277 uint16_t
1278 TcpSocketBase::AdvertisedWindowSize ()
1279 {
1280 uint32_t max = 0xffff;
1281 return std::min (m_rxBuffer.MaxBufferSize () - m_rxBuffer.Size (), max);
1282 }
1283
1284 // Receipt of new packet, put into Rx buffer
1285 void
1286 TcpSocketBase::ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader)
1287 {
1288 NS_LOG_FUNCTION (this << tcpHeader);
1289 NS_LOG_LOGIC ("seq " << tcpHeader.GetSequenceNumber () <<
1290 " ack " << tcpHeader.GetAckNumber () <<
1291 " pkt size " << p->GetSize () );
1292
1293 // Put into Rx buffer
1294 States_t origState = m_state;
1295 SequenceNumber origSeq = m_rxBuffer.NextRxSeq ();
1296 if (!m_rxBuffer.Add (p, tcpHeader))
1297 { // Insert failed: No data or RX buffer full
1298 SendEmptyPacket (TcpHeader::ACK);
1299 return;
1300 }
1301 // Now send a new ACK packet acknowledging all received and delivered data
1302 if (++m_delAckCount >= m_delAckMaxCount)
1303 {
1304 SendEmptyPacket (TcpHeader::ACK);
1305 }
1306 else if (m_delAckEvent.IsExpired ())
1307 {
1308 m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &TcpSocketBase::DelA ckTimeout, this);
1309 }
1310 // Notify app to receive if necessary
1311 if (origSeq < m_rxBuffer.NextRxSeq ())
1312 { // NextRxSeq advanced, we have something to send to the app
1313 if (!m_shutdownRecv) NotifyDataRecv ();
1314 // Handle exceptions
1315 if (m_closeNotified)
1316 {
1317 NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif");
1318 }
1319 if ((m_rxBuffer.Finished () || (origState > ESTABLISHED)) && (m_rxBuffer.S ize () == 0))
1320 { // No more data to forward to app, we can close now
1321 PeerClose (p, tcpHeader);
1322 }
1323 }
1324 }
1325
1326 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
1327 // when the three-way handshake completed. This cancels retransmission timer
1328 // and advances Tx window
1329 void
1330 TcpSocketBase::NewAck (SequenceNumber const& ack)
1331 {
1332 NS_LOG_FUNCTION (this << ack);
1333
1334 if (m_state != SYN_RCVD)
1335 { // Set RTO unless the ACK is received in SYN_RCVD state
1336 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir e at " <<
1337 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)). GetSeconds ());
1338 m_retxEvent.Cancel ();
1339 // On recieving a "New" ack we restart retransmission timer .. RFC 2988
1340 Time rto = m_rtt->RetransmitTimeout ();
1341 NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
1342 Simulator::Now ().GetSeconds () << " to expire at time " <<
1343 (Simulator::Now () + rto).GetSeconds ());
1344 m_retxEvent = Simulator::Schedule (rto, &TcpSocketBase::ReTxTimeout, this) ;
1345 }
1346 if (m_rxWindowSize == 0 && m_persistEvent.IsExpired ())
1347 { // Zero window: Enter persist state to send 1 byte to probe
1348 NS_LOG_LOGIC (this << "Enter zerowindow persist state");
1349 NS_LOG_LOGIC (this << "Cancelled ReTxTimeout event which was set to expire at " <<
1350 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)). GetSeconds ());
1351 m_retxEvent.Cancel ();
1352 NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1353 Simulator::Now ().GetSeconds () << " to expire at time " <<
1354 (Simulator::Now () + m_persistTime).GetSeconds ());
1355 m_persistEvent = Simulator::Schedule (m_persistTime, &TcpSocketBase::Persi stTimeout, this);
1356 NS_ASSERT (m_persistTime == Simulator::GetDelayLeft (m_persistEvent));
1357 }
1358 // Note the highest ACK and tell app to send more
1359 NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
1360 " numberAck " << (ack - m_txBuffer.HeadSeq ())); // Number bytes ack'ed
1361 m_txBuffer.SetHeadSeq (ack);
1362 if (GetTxAvailable () > 0)
1363 {
1364 NotifySend (GetTxAvailable ());
1365 }
1366 if (ack > m_nextTxSequence)
1367 {
1368 m_nextTxSequence = ack; // If advanced
1369 }
1370 if (m_txBuffer.Size () == 0)
1371 { // No retransmit timer if no data to retransmit
1372 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir e at " <<
1373 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)). GetSeconds ());
1374 m_retxEvent.Cancel ();
1375 }
1376 // Try to send more data
1377 SendPendingData (m_connected);
1378 }
1379
1380 // Retransmit timeout
1381 void
1382 TcpSocketBase::ReTxTimeout ()
1383 {
1384 NS_LOG_FUNCTION (this);
1385 NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().Get Seconds ());
1386 // If erroneous timeout in closed/timed-wait state, just return
1387 if (m_state == CLOSED || m_state == TIME_WAIT) return;
1388 // If all data are received, just return
1389 if (m_txBuffer.HeadSeq () >= m_nextTxSequence) return;
1390
1391 Retransmit ();
Adrian 2010/06/25 08:46:10 Put the variant-specific behaviour in Retransmit()
1392 }
1393
1394 void
1395 TcpSocketBase::DelAckTimeout ()
1396 {
1397 SendEmptyPacket (TcpHeader::ACK);
1398 }
1399
1400 void
1401 TcpSocketBase::LastAckTimeout ()
1402 {
1403 m_lastAckEvent.Cancel ();
1404 if (m_state == LAST_ACK)
1405 {
1406 CloseAndNotify ();
1407 }
1408 if (!m_closeNotified)
1409 {
1410 m_closeNotified = true;
1411 }
1412 }
1413
1414 // Send 1-byte data to probe for the window size at the receiver when
1415 // the local knowledge tells that the receiver has zero window size
1416 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
1417 void
1418 TcpSocketBase::PersistTimeout ()
1419 {
1420 NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ()) ;
1421 m_persistTime = std::min (Seconds (60), Scalar (2) * m_persistTime); // max pe rsist timeout = 60s
1422 Ptr<Packet> p = m_txBuffer.CopyFromSeq (1, m_nextTxSequence);
1423 TcpHeader tcpHeader;
1424 tcpHeader.SetSequenceNumber (m_nextTxSequence);
1425 tcpHeader.SetAckNumber (m_rxBuffer.NextRxSeq ());
1426 tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
1427 tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
1428 tcpHeader.SetWindowSize (AdvertisedWindowSize ());
1429
1430 m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
1431 m_endPoint->GetPeerAddress (), m_boundnetdevice);
1432 NS_LOG_LOGIC ("Schedule persist timeout at time "
1433 << Simulator::Now ().GetSeconds () << " to expire at time "
1434 << (Simulator::Now () + m_persistTime).GetSeconds ());
1435 m_persistEvent = Simulator::Schedule (m_persistTime, &TcpSocketBase::PersistTi meout, this);
1436 }
1437
1438 void
1439 TcpSocketBase::Retransmit ()
1440 {
1441 m_nextTxSequence = m_txBuffer.HeadSeq (); // Start from highest Ack
1442 m_rtt->IncreaseMultiplier (); // Double the timeout value for next retx timer
1443 m_dupAckCount = 0;
1444 DoRetransmit (); // Retransmit the packet
1445 }
Adrian 2010/06/25 08:46:10 This is the baseline behaviour (as of RFC793, exce
1446
1447 void
1448 TcpSocketBase::DoRetransmit ()
1449 {
Adrian 2010/06/25 08:46:10 DoRetransmit blindly re-send the packet at m_nextT
1450 NS_LOG_FUNCTION (this);
1451 uint8_t flags = TcpHeader::ACK;
1452 // Retransmit SYN packet
1453 if (m_state == SYN_SENT)
1454 {
1455 if (m_cnCount > 0)
1456 {
1457 SendEmptyPacket (TcpHeader::SYN);
1458 }
1459 else
1460 {
1461 NotifyConnectionFailed ();
1462 }
1463 return;
1464 }
1465 // Retransmit non-data packet: Only if in FIN_WAIT_1 state
1466 if (m_txBuffer.SizeFromSeq (m_nextTxSequence) == 0)
1467 {
1468 if (m_state == FIN_WAIT_1)
1469 { // Must have lost FIN, re-send
1470 SendEmptyPacket (TcpHeader::FIN);
1471 }
1472 return;
1473 }
1474 // Retransmit a data packet: Extract data
1475 NS_ASSERT (m_nextTxSequence == m_txBuffer.HeadSeq ());
1476 Ptr<Packet> p = m_txBuffer.CopyFromSeq (m_segmentSize, m_nextTxSequence);
1477 // Close-on-Empty check
1478 if (m_closeOnEmpty && m_txBuffer.SizeFromSeq (m_nextTxSequence) == p->GetSize ())
1479 {
1480 flags |= TcpHeader::FIN;
1481 }
1482 // Reset transmission timeout
1483 NS_LOG_LOGIC ("TcpSocketBase " << this << " retxing seq " << m_txBuffer.HeadSe q ());
1484 if (m_retxEvent.IsExpired ())
1485 {
1486 Time rto = m_rtt->RetransmitTimeout ();
1487 NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
1488 Simulator::Now ().GetSeconds () << " to expire at time " <<
1489 (Simulator::Now () + rto).GetSeconds ());
1490 m_retxEvent = Simulator::Schedule (rto, &TcpSocketBase::ReTxTimeout, this) ;
1491 }
1492 m_rtt->SentSeq (m_txBuffer.HeadSeq (), p->GetSize ());
1493 // And send the packet
1494 TcpHeader tcpHeader;
1495 tcpHeader.SetSequenceNumber (m_nextTxSequence);
1496 tcpHeader.SetAckNumber (m_rxBuffer.NextRxSeq ());
1497 tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
1498 tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
1499 tcpHeader.SetFlags (flags);
1500 tcpHeader.SetWindowSize (AdvertisedWindowSize ());
1501
1502 m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
1503 m_endPoint->GetPeerAddress (), m_boundnetdevice);
1504 }
1505
1506 void
1507 TcpSocketBase::CancelAllTimers ()
1508 {
1509 m_retxEvent.Cancel ();
1510 m_persistEvent.Cancel ();
1511 m_delAckEvent.Cancel ();
1512 m_lastAckEvent.Cancel ();
1513 }
1514
1515 /* Below are the attribute get/set functions */
1516
1517 void
1518 TcpSocketBase::SetSndBufSize (uint32_t size)
1519 {
1520 m_txBuffer.SetMaxBufferSize (size);
1521 }
1522
1523 uint32_t
1524 TcpSocketBase::GetSndBufSize (void) const
1525 {
1526 return m_txBuffer.MaxBufferSize ();
1527 }
1528
1529 void
1530 TcpSocketBase::SetRcvBufSize (uint32_t size)
1531 {
1532 m_rxBuffer.SetMaxBufferSize (size);
1533 }
1534
1535 uint32_t
1536 TcpSocketBase::GetRcvBufSize (void) const
1537 {
1538 return m_rxBuffer.MaxBufferSize ();
1539 }
1540
1541 void
1542 TcpSocketBase::SetSegSize (uint32_t size)
1543 {
1544 m_segmentSize = size;
1545 NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamicall y.");
1546 }
1547
1548 uint32_t
1549 TcpSocketBase::GetSegSize (void) const
1550 {
1551 return m_segmentSize;
1552 }
1553
1554 void
1555 TcpSocketBase::SetConnTimeout (Time timeout)
1556 {
1557 m_cnTimeout = timeout;
1558 }
1559
1560 Time
1561 TcpSocketBase::GetConnTimeout (void) const
1562 {
1563 return m_cnTimeout;
1564 }
1565
1566 void
1567 TcpSocketBase::SetConnCount (uint32_t count)
1568 {
1569 m_cnCount = count;
1570 }
1571
1572 uint32_t
1573 TcpSocketBase::GetConnCount (void) const
1574 {
1575 return m_cnCount;
1576 }
1577
1578 void
1579 TcpSocketBase::SetDelAckTimeout (Time timeout)
1580 {
1581 m_delAckTimeout = timeout;
1582 }
1583
1584 Time
1585 TcpSocketBase::GetDelAckTimeout (void) const
1586 {
1587 return m_delAckTimeout;
1588 }
1589
1590 void
1591 TcpSocketBase::SetDelAckMaxCount (uint32_t count)
1592 {
1593 m_delAckMaxCount = count;
1594 }
1595
1596 uint32_t
1597 TcpSocketBase::GetDelAckMaxCount (void) const
1598 {
1599 return m_delAckMaxCount;
1600 }
1601
1602 } // namespace ns3
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b