nsc: move nsc glue code from nsc-tcp-l4-protocol to node/nsc-glue.cc.
known problems:
- sim_interface.h is duplicated
- nsc-glue.cc adds hooks in node.cc, "hijacks" incoming packets
- nsc-glue exports NSCs INetStack (instead of wrapping it completely)
- nsc-tcp-l4-protocol and nsc-tcp-socket-impl make calls into nsc-glue
- nsc-tcp-socket-impl should really be "nsc-socket-core" (or something
like that)
needs fixing on nsc side:
- no support for multiple interfaces yet (also not yet supported
on nsc side)
- nsc initialisation still tied to IP (Adding an Interface and assigning the
IP address is a single step; it should be separate)
maybe there is more.
There is a NSC_NEXT define in nsc-glue.h, its main purpose is to flag
the places where the NSC API needs to be adapted to support multiple
interfaces in nsc.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation;
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
17 * Author: Florian Westphal <fw@strlen.de>
21 #include "ns3/inet-socket-address.h"
24 #include "ipv4-end-point.h"
25 #include "nsc-tcp-l4-protocol.h"
26 #include "nsc-tcp-socket-impl.h"
27 #include "ns3/simulation-singleton.h"
28 #include "tcp-typedefs.h"
29 #include "ns3/simulator.h"
30 #include "ns3/packet.h"
31 #include "ns3/uinteger.h"
32 #include "ns3/trace-source-accessor.h"
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
40 #include "sim_interface.h"
41 #include "sim_errno.h"
43 NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
49 NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
52 NscTcpSocketImpl::GetTypeId ()
54 static TypeId tid = TypeId("ns3::NscTcpSocketImpl")
55 .SetParent<TcpSocket> ()
56 .AddTraceSource ("CongestionWindow",
57 "The TCP connection's congestion window",
58 MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
63 NscTcpSocketImpl::NscTcpSocketImpl ()
67 m_localAddress (Ipv4Address::GetZero ()),
69 m_peerAddress ("0.0.0.0", 0),
70 m_errno (ERROR_NOTERROR),
71 m_shutdownSend (false),
72 m_shutdownRecv (false),
75 m_closeOnEmpty (false),
78 m_lastMeasuredRtt (Seconds(0.0))
80 NS_LOG_FUNCTION (this);
83 NscTcpSocketImpl::NscTcpSocketImpl(const NscTcpSocketImpl& sock)
84 : TcpSocket(sock), //copy the base class callbacks
85 m_delAckMaxCount (sock.m_delAckMaxCount),
86 m_delAckTimeout (sock.m_delAckTimeout),
90 m_remoteAddress (sock.m_remoteAddress),
91 m_remotePort (sock.m_remotePort),
92 m_localAddress (sock.m_localAddress),
93 m_localPort (sock.m_localPort),
94 m_peerAddress (sock.m_peerAddress),
95 m_errno (sock.m_errno),
96 m_shutdownSend (sock.m_shutdownSend),
97 m_shutdownRecv (sock.m_shutdownRecv),
98 m_connected (sock.m_connected),
99 m_state (sock.m_state),
100 m_closeOnEmpty (sock.m_closeOnEmpty),
101 m_segmentSize (sock.m_segmentSize),
102 m_rxWindowSize (sock.m_rxWindowSize),
103 m_advertisedWindowSize (sock.m_advertisedWindowSize),
104 m_cWnd (sock.m_cWnd),
105 m_ssThresh (sock.m_ssThresh),
106 m_initialCWnd (sock.m_initialCWnd),
108 m_lastMeasuredRtt (Seconds(0.0)),
109 m_cnTimeout (sock.m_cnTimeout),
110 m_cnCount (sock.m_cnCount),
113 m_sndBufSize (sock.m_sndBufSize)
115 NS_LOG_FUNCTION_NOARGS ();
116 NS_LOG_LOGIC("Invoked the copy constructor");
117 //copy the pending data if necessary
118 if(!sock.m_txBuffer.empty () )
120 m_txBuffer = sock.m_txBuffer;
122 //copy the rtt if necessary
125 m_rtt = sock.m_rtt->Copy();
127 //can't "copy" the endpoint just yes, must do this when we know the peer info
128 //too; this is in SYN_ACK_TX
131 NscTcpSocketImpl::~NscTcpSocketImpl ()
133 NS_LOG_FUNCTION(this);
137 NS_ASSERT (m_tcp != 0);
139 * Note that this piece of code is a bit tricky:
140 * when DeAllocate is called, it will call into
141 * Ipv4EndPointDemux::Deallocate which triggers
142 * a delete of the associated endPoint which triggers
143 * in turn a call to the method ::Destroy below
144 * will will zero the m_endPoint field.
146 NS_ASSERT (m_endPoint != 0);
147 m_tcp->DeAllocate (m_endPoint);
148 NS_ASSERT (m_endPoint == 0);
154 NscTcpSocketImpl::SetNode (Ptr<Node> node)
157 // Initialize some variables
158 m_cWnd = m_initialCWnd * m_segmentSize;
159 m_rxWindowSize = m_advertisedWindowSize;
163 NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
166 m_nscTcpSocket = m_node->GetNscInetStack()->new_tcp_socket();
169 NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
175 enum Socket::SocketErrno
176 NscTcpSocketImpl::GetErrno (void) const
178 NS_LOG_FUNCTION_NOARGS ();
183 NscTcpSocketImpl::GetNode (void) const
185 NS_LOG_FUNCTION_NOARGS ();
190 NscTcpSocketImpl::Destroy (void)
192 NS_LOG_FUNCTION_NOARGS ();
198 NscTcpSocketImpl::FinishBind (void)
200 NS_LOG_FUNCTION_NOARGS ();
205 m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
206 m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
207 m_localAddress = m_endPoint->GetLocalAddress ();
208 m_localPort = m_endPoint->GetLocalPort ();
213 NscTcpSocketImpl::Bind (void)
215 NS_LOG_FUNCTION_NOARGS ();
216 m_endPoint = m_tcp->Allocate ();
217 return FinishBind ();
220 NscTcpSocketImpl::Bind (const Address &address)
222 NS_LOG_FUNCTION (this<<address);
223 if (!InetSocketAddress::IsMatchingType (address))
227 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
228 Ipv4Address ipv4 = transport.GetIpv4 ();
229 uint16_t port = transport.GetPort ();
230 if (ipv4 == Ipv4Address::GetAny () && port == 0)
232 m_endPoint = m_tcp->Allocate ();
233 NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
235 else if (ipv4 == Ipv4Address::GetAny () && port != 0)
237 m_endPoint = m_tcp->Allocate (port);
238 NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
240 else if (ipv4 != Ipv4Address::GetAny () && port == 0)
242 m_endPoint = m_tcp->Allocate (ipv4);
243 NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
245 else if (ipv4 != Ipv4Address::GetAny () && port != 0)
247 m_endPoint = m_tcp->Allocate (ipv4, port);
248 NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
252 return FinishBind ();
256 NscTcpSocketImpl::ShutdownSend (void)
258 NS_LOG_FUNCTION_NOARGS ();
259 m_shutdownSend = true;
263 NscTcpSocketImpl::ShutdownRecv (void)
265 NS_LOG_FUNCTION_NOARGS ();
266 m_shutdownRecv = true;
271 NscTcpSocketImpl::Close (void)
273 NS_LOG_FUNCTION (this << m_state);
275 if (m_state == CLOSED)
279 if (!m_txBuffer.empty ())
280 { // App close with pending data must wait until all data transmitted
281 m_closeOnEmpty = true;
282 NS_LOG_LOGIC("Socket " << this <<
283 " deferring close, state " << m_state);
287 m_nscTcpSocket->disconnect();
294 NscTcpSocketImpl::Connect (const Address & address)
296 NS_LOG_FUNCTION (this << address);
301 NS_ASSERT (m_endPoint == 0);
304 NS_ASSERT (m_endPoint != 0);
306 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
307 m_remoteAddress = transport.GetIpv4 ();
308 m_remotePort = transport.GetPort ();
310 std::ostringstream ss;
311 m_remoteAddress.Print(ss);
312 std::string ipstring = ss.str ();
314 m_nscTcpSocket->connect(ipstring.c_str (), m_remotePort);
320 NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
322 NS_LOG_FUNCTION (this << p);
324 NS_ASSERT (p->GetSize () > 0);
325 if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
327 if (p->GetSize () > GetTxAvailable ())
329 m_errno = ERROR_MSGSIZE;
333 uint32_t sent = p->GetSize ();
334 if (m_state == ESTABLISHED)
337 m_txBufferSize += sent;
341 { // SYN_SET -- Queue Data
343 m_txBufferSize += sent;
349 m_errno = ERROR_NOTCONN;
355 NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
357 NS_LOG_FUNCTION (this << address << p);
360 m_errno = ERROR_NOTCONN;
365 return Send (p, flags); //drop the address according to BSD manpages
370 NscTcpSocketImpl::GetTxAvailable (void) const
372 NS_LOG_FUNCTION_NOARGS ();
373 if (m_txBufferSize != 0)
375 NS_ASSERT (m_txBufferSize <= m_sndBufSize);
376 return m_sndBufSize - m_txBufferSize;
385 NscTcpSocketImpl::Listen (void)
387 NS_LOG_FUNCTION (this);
388 m_nscTcpSocket->listen(m_localPort);
395 NscTcpSocketImpl::NSCWakeup ()
399 if (!m_nscTcpSocket->is_connected())
401 m_state = ESTABLISHED;
402 Simulator::ScheduleNow(&NscTcpSocketImpl::ConnectionSucceeded, this);
403 // fall through to schedule read/write events
405 if (!m_txBuffer.empty ())
406 Simulator::ScheduleNow(&NscTcpSocketImpl::SendPendingData, this);
407 Simulator::ScheduleNow(&NscTcpSocketImpl::ReadPendingData, this);
410 Simulator::ScheduleNow(&NscTcpSocketImpl::Accept, this);
414 NS_LOG_DEBUG (this << " invalid state: " << m_state);
419 NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
421 NS_LOG_FUNCTION_NOARGS ();
422 if (m_deliveryQueue.empty() )
424 m_errno = ERROR_AGAIN;
427 Ptr<Packet> p = m_deliveryQueue.front ();
428 if (p->GetSize () <= maxSize)
430 m_deliveryQueue.pop ();
431 m_rxAvailable -= p->GetSize ();
435 m_errno = ERROR_AGAIN;
442 NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
443 Address &fromAddress)
445 NS_LOG_FUNCTION (this << maxSize << flags);
446 Ptr<Packet> packet = Recv (maxSize, flags);
449 SocketAddressTag tag;
451 found = packet->PeekPacketTag (tag);
453 fromAddress = tag.GetAddress ();
459 NscTcpSocketImpl::GetSockName (Address &address) const
461 NS_LOG_FUNCTION_NOARGS ();
462 address = InetSocketAddress(m_localAddress, m_localPort);
467 NscTcpSocketImpl::GetRxAvailable (void) const
469 NS_LOG_FUNCTION_NOARGS ();
470 // We separately maintain this state to avoid walking the queue
471 // every time this might be called
472 return m_rxAvailable;
476 NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
481 void NscTcpSocketImpl::CompleteFork(void)
483 // The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
484 // are bogus, but this isn't important at the moment, because
485 // address <-> Socket handling is done by NSC internally.
486 // We only need to add the new ns-3 socket to the list of sockets, so
487 // we use plain Allocate() instead of Allocate(m_localAddress, ... )
488 struct sockaddr_in sin;
489 size_t sin_len = sizeof(sin);
491 if (0 == m_nscTcpSocket->getpeername((struct sockaddr*) &sin, &sin_len)) {
492 m_remotePort = ntohs(sin.sin_port);
493 m_remoteAddress = m_remoteAddress.Deserialize((const uint8_t*) &sin.sin_addr);
494 m_peerAddress = InetSocketAddress(m_remoteAddress, m_remotePort);
497 m_endPoint = m_tcp->Allocate ();
499 //the cloned socket with be in listen state, so manually change state
500 NS_ASSERT(m_state == LISTEN);
501 m_state = ESTABLISHED;
503 sin_len = sizeof(sin);
505 if (0 == m_nscTcpSocket->getsockname((struct sockaddr *) &sin, &sin_len))
506 m_localAddress = m_localAddress.Deserialize((const uint8_t*) &sin.sin_addr);
508 NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from "
509 << m_remoteAddress << ":" << m_remotePort
510 << " to " << m_localAddress << ":" << m_localPort);
511 //equivalent to FinishBind
512 m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
513 m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
515 NotifyNewConnectionCreated (this, m_peerAddress);
518 void NscTcpSocketImpl::ConnectionSucceeded()
519 { // We would preferred to have scheduled an event directly to
520 // NotifyConnectionSucceeded, but (sigh) these are protected
521 // and we can get the address of it :(
522 struct sockaddr_in sin;
523 size_t sin_len = sizeof(sin);
524 if (0 == m_nscTcpSocket->getsockname((struct sockaddr *) &sin, &sin_len)) {
525 m_localAddress = m_localAddress.Deserialize((const uint8_t*)&sin.sin_addr);
526 m_localPort = ntohs(sin.sin_port);
529 NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
530 << m_remoteAddress << ":" << m_remotePort
531 << " from " << m_localAddress << ":" << m_localPort);
532 NotifyConnectionSucceeded();
536 bool NscTcpSocketImpl::Accept (void)
538 if (m_state == CLOSED)
539 { // Happens if application closes listening socket after Accept() was scheduled.
542 NS_ASSERT (m_state == LISTEN);
544 if (!m_nscTcpSocket->is_listening())
548 INetStreamSocket *newsock;
549 int res = m_nscTcpSocket->accept(&newsock);
554 // We could obtain a fromAddress using getpeername, but we've already
555 // finished the tcp handshake here, i.e. this is a new connection
556 // and not a connection request.
557 // if (!NotifyConnectionRequest(fromAddress))
561 Ptr<NscTcpSocketImpl> newSock = Copy ();
562 newSock->m_nscTcpSocket = newsock;
563 NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
565 Simulator::ScheduleNow (&NscTcpSocketImpl::CompleteFork, newSock);
569 bool NscTcpSocketImpl::ReadPendingData (void)
571 if (m_state != ESTABLISHED)
576 uint8_t buffer[8192];
577 len = sizeof(buffer);
578 m_errno = ERROR_NOTERROR;
579 err = m_nscTcpSocket->read_data(buffer, &len);
580 if (err == 0 && len == 0)
582 NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
586 m_errno = GetNativeNs3Errno(err);
589 case ERROR_NOTERROR: break; // some data was sent
590 case ERROR_AGAIN: return false;
592 NS_LOG_WARN ("Error (" << err << ") " <<
593 "during read_data, ns-3 errno set to" << m_errno);
598 Ptr<Packet> p = Create<Packet> (buffer, len);
600 SocketAddressTag tag;
602 tag.SetAddress (m_peerAddress);
603 p->AddPacketTag (tag);
604 m_deliveryQueue.push (p);
605 m_rxAvailable += p->GetSize ();
611 bool NscTcpSocketImpl::SendPendingData (void)
613 NS_LOG_FUNCTION (this);
614 NS_LOG_LOGIC ("ENTERING SendPendingData");
616 if (m_txBuffer.empty ())
622 size_t size, written = 0;
625 NS_ASSERT (!m_txBuffer.empty ());
626 Ptr<Packet> &p = m_txBuffer.front ();
627 size = p->GetSize ();
628 NS_ASSERT (size > 0);
630 m_errno = ERROR_NOTERROR;
631 ret = m_nscTcpSocket->send_data((const char *)p->PeekData (), size);
638 NS_ASSERT (m_txBufferSize >= (size_t)ret);
639 m_txBufferSize -= ret;
641 if ((size_t)ret < size)
643 p->RemoveAtStart(ret);
649 if (m_txBuffer.empty ())
653 m_nscTcpSocket->disconnect();
658 } while ((size_t) ret == size);
662 Simulator::ScheduleNow(&NscTcpSocketImpl::NotifyDataSent, this, ret);
668 Ptr<NscTcpSocketImpl> NscTcpSocketImpl::Copy ()
670 return CopyObject<NscTcpSocketImpl> (this);
674 NscTcpSocketImpl::SetSndBufSize (uint32_t size)
680 NscTcpSocketImpl::GetSndBufSize (void) const
686 NscTcpSocketImpl::SetRcvBufSize (uint32_t size)
692 NscTcpSocketImpl::GetRcvBufSize (void) const
698 NscTcpSocketImpl::SetSegSize (uint32_t size)
700 m_segmentSize = size;
704 NscTcpSocketImpl::GetSegSize (void) const
706 return m_segmentSize;
710 NscTcpSocketImpl::SetAdvWin (uint32_t window)
712 m_advertisedWindowSize = window;
716 NscTcpSocketImpl::GetAdvWin (void) const
718 return m_advertisedWindowSize;
722 NscTcpSocketImpl::SetSSThresh (uint32_t threshold)
724 m_ssThresh = threshold;
728 NscTcpSocketImpl::GetSSThresh (void) const
734 NscTcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
736 m_initialCWnd = cwnd;
740 NscTcpSocketImpl::GetInitialCwnd (void) const
742 return m_initialCWnd;
746 NscTcpSocketImpl::SetConnTimeout (Time timeout)
748 m_cnTimeout = timeout;
752 NscTcpSocketImpl::GetConnTimeout (void) const
758 NscTcpSocketImpl::SetConnCount (uint32_t count)
764 NscTcpSocketImpl::GetConnCount (void) const
770 NscTcpSocketImpl::SetDelAckTimeout (Time timeout)
772 m_delAckTimeout = timeout;
776 NscTcpSocketImpl::GetDelAckTimeout (void) const
778 return m_delAckTimeout;
782 NscTcpSocketImpl::SetDelAckMaxCount (uint32_t count)
784 m_delAckMaxCount = count;
788 NscTcpSocketImpl::GetDelAckMaxCount (void) const
790 return m_delAckMaxCount;
793 enum Socket::SocketErrno
794 NscTcpSocketImpl::GetNativeNs3Errno(int error) const
800 return ERROR_NOTERROR;
802 err = (enum nsc_errno) error;
805 case NSC_EADDRINUSE: // fallthrough
806 case NSC_EADDRNOTAVAIL: return ERROR_AFNOSUPPORT;
807 case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
808 case NSC_EAGAIN: return ERROR_AGAIN;
809 case NSC_EISCONN: // fallthrough
810 case NSC_EALREADY: return ERROR_ISCONN;
811 case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; // XXX, better mapping?
812 case NSC_ECONNRESET: // for no, all of these fall through
814 case NSC_ENETUNREACH:
815 case NSC_EHOSTUNREACH: return ERROR_NOROUTETOHOST;
816 case NSC_EMSGSIZE: return ERROR_MSGSIZE;
817 case NSC_ENOTCONN: return ERROR_NOTCONN;
818 case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
819 case NSC_ETIMEDOUT: return ERROR_NOTCONN; // XXX - this mapping isn't correct
820 case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
821 // but is triggered by e.g. show_config().
822 case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
824 NS_ASSERT_MSG(0, "Unknown NSC error");