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

Unified Diff: src/internet/model/tcp-header.cc

Issue 24900043: TCP Window Scale and Timestamps Implementation
Patch Set: Created 10 years, 3 months ago
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 side-by-side diff with in-line comments
Download patch
Index: src/internet/model/tcp-header.cc
===================================================================
--- a/src/internet/model/tcp-header.cc
+++ b/src/internet/model/tcp-header.cc
@@ -23,9 +23,12 @@
#include "tcp-header.h"
#include "ns3/buffer.h"
#include "ns3/address-utils.h"
+#include "ns3/log.h"
namespace ns3 {
+NS_LOG_COMPONENT_DEFINE ("TcpHeader");
+
NS_OBJECT_ENSURE_REGISTERED (TcpHeader);
TcpHeader::TcpHeader ()
@@ -52,74 +55,104 @@
m_calcChecksum = true;
}
-void TcpHeader::SetSourcePort (uint16_t port)
+void
+TcpHeader::SetSourcePort (uint16_t port)
{
m_sourcePort = port;
}
-void TcpHeader::SetDestinationPort (uint16_t port)
+
+void
+TcpHeader::SetDestinationPort (uint16_t port)
{
m_destinationPort = port;
}
-void TcpHeader::SetSequenceNumber (SequenceNumber32 sequenceNumber)
+
+void
+TcpHeader::SetSequenceNumber (SequenceNumber32 sequenceNumber)
{
m_sequenceNumber = sequenceNumber;
}
-void TcpHeader::SetAckNumber (SequenceNumber32 ackNumber)
+
+void
+TcpHeader::SetAckNumber (SequenceNumber32 ackNumber)
{
m_ackNumber = ackNumber;
}
-void TcpHeader::SetLength (uint8_t length)
+
+void
+TcpHeader::SetLength (uint8_t length)
{
m_length = length;
}
-void TcpHeader::SetFlags (uint8_t flags)
+
+void
+TcpHeader::SetFlags (uint8_t flags)
{
m_flags = flags;
}
-void TcpHeader::SetWindowSize (uint16_t windowSize)
+
+void
+TcpHeader::SetWindowSize (uint16_t windowSize)
{
m_windowSize = windowSize;
}
-void TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
+
+void
+TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
{
m_urgentPointer = urgentPointer;
}
-uint16_t TcpHeader::GetSourcePort () const
+uint16_t
+TcpHeader::GetSourcePort () const
{
return m_sourcePort;
}
-uint16_t TcpHeader::GetDestinationPort () const
+
+uint16_t
+TcpHeader::GetDestinationPort () const
{
return m_destinationPort;
}
-SequenceNumber32 TcpHeader::GetSequenceNumber () const
+
+SequenceNumber32
+TcpHeader::GetSequenceNumber () const
{
return m_sequenceNumber;
}
-SequenceNumber32 TcpHeader::GetAckNumber () const
+
+SequenceNumber32
+TcpHeader::GetAckNumber () const
{
return m_ackNumber;
}
-uint8_t TcpHeader::GetLength () const
+
+uint8_t
+TcpHeader::GetLength () const
{
return m_length;
}
-uint8_t TcpHeader::GetFlags () const
+
+uint8_t
+TcpHeader::GetFlags () const
{
return m_flags;
}
-uint16_t TcpHeader::GetWindowSize () const
+
+uint16_t
+TcpHeader::GetWindowSize () const
{
return m_windowSize;
}
-uint16_t TcpHeader::GetUrgentPointer () const
+
+uint16_t
+TcpHeader::GetUrgentPointer () const
{
return m_urgentPointer;
}
-void
-TcpHeader::InitializeChecksum (Ipv4Address source,
+void
+TcpHeader::InitializeChecksum (Ipv4Address source,
Ipv4Address destination,
uint8_t protocol)
{
@@ -128,8 +161,8 @@
m_protocol = protocol;
}
-void
-TcpHeader::InitializeChecksum (Ipv6Address source,
+void
+TcpHeader::InitializeChecksum (Ipv6Address source,
Ipv6Address destination,
uint8_t protocol)
{
@@ -138,8 +171,8 @@
m_protocol = protocol;
}
-void
-TcpHeader::InitializeChecksum (Address source,
+void
+TcpHeader::InitializeChecksum (Address source,
Address destination,
uint8_t protocol)
{
@@ -167,7 +200,7 @@
WriteTo (it, m_source);
WriteTo (it, m_destination);
- if (Ipv4Address::IsMatchingType(m_source))
+ if (Ipv4Address::IsMatchingType (m_source))
{
it.WriteU8 (0); /* protocol */
it.WriteU8 (m_protocol); /* protocol */
@@ -197,7 +230,7 @@
return m_goodChecksum;
}
-TypeId
+TypeId
TcpHeader::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpHeader")
@@ -206,70 +239,103 @@
;
return tid;
}
-TypeId
+
+TypeId
TcpHeader::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
-void TcpHeader::Print (std::ostream &os) const
+
+void
+TcpHeader::Print (std::ostream &os) const
{
- os << m_sourcePort << " > " << m_destinationPort;
- if(m_flags!=0)
+ os << "length: " << GetSerializedSize () << " "
+ << m_sourcePort << " > " << m_destinationPort;
+ if (m_flags != 0)
{
- os<<" [";
- if((m_flags & FIN) != 0)
+ os << " [";
+ if ((m_flags & FIN) != 0)
{
- os<<" FIN ";
+ os << " FIN ";
}
- if((m_flags & SYN) != 0)
+ if ((m_flags & SYN) != 0)
{
- os<<" SYN ";
+ os << " SYN ";
}
- if((m_flags & RST) != 0)
+ if ((m_flags & RST) != 0)
{
- os<<" RST ";
+ os << " RST ";
}
- if((m_flags & PSH) != 0)
+ if ((m_flags & PSH) != 0)
{
- os<<" PSH ";
+ os << " PSH ";
}
- if((m_flags & ACK) != 0)
+ if ((m_flags & ACK) != 0)
{
- os<<" ACK ";
+ os << " ACK ";
}
- if((m_flags & URG) != 0)
+ if ((m_flags & URG) != 0)
{
- os<<" URG ";
+ os << " URG ";
}
- if((m_flags & ECE) != 0)
+ if ((m_flags & ECE) != 0)
{
- os<<" ECE ";
+ os << " ECE ";
}
- if((m_flags & CWR) != 0)
+ if ((m_flags & CWR) != 0)
{
- os<<" CWR ";
+ os << " CWR ";
}
- os<<"]";
+ os << "]";
}
- os<<" Seq="<<m_sequenceNumber<<" Ack="<<m_ackNumber<<" Win="<<m_windowSize;
+ os << " Seq=" << m_sequenceNumber << " Ack=" << m_ackNumber << " Win=" << m_windowSize;
+
+ // Print the options
+ for (std::list<Ptr<TcpOption> >::const_iterator op = m_options.begin (); op != m_options.end (); ++op)
+ {
+ os << " " << (*op)->GetInstanceTypeId ().GetName () << "(";
+ (*op)->Print (os);
+ os << ")";
+ }
}
-uint32_t TcpHeader::GetSerializedSize (void) const
+
+uint32_t
+TcpHeader::GetSerializedSize (void) const
{
- return 4*m_length;
+ return 4 * GetLength ();
Peter Barnes 2013/12/26 21:25:45 Why do you call GetLength instead of referring to
}
-void TcpHeader::Serialize (Buffer::Iterator start) const
+
+void
+TcpHeader::Serialize (Buffer::Iterator start) const
{
+ NS_LOG_FUNCTION (this);
Buffer::Iterator i = start;
i.WriteHtonU16 (m_sourcePort);
i.WriteHtonU16 (m_destinationPort);
i.WriteHtonU32 (m_sequenceNumber.GetValue ());
i.WriteHtonU32 (m_ackNumber.GetValue ());
- i.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
+ i.WriteHtonU16 (GetLength () << 12 | m_flags); //reserved bits are all zero
Peter Barnes 2013/12/26 21:25:45 Why do you call GetLength instead of referring to
i.WriteHtonU16 (m_windowSize);
i.WriteHtonU16 (0);
i.WriteHtonU16 (m_urgentPointer);
- if(m_calcChecksum)
+ //Serialize options if they exist
+ unsigned optionLen = 0;
+ for (std::list<Ptr<TcpOption> >::const_iterator op = m_options.begin (); op != m_options.end (); ++op)
+ {
+ optionLen += (*op)->GetSerializedSize ();
+ (*op)->Serialize (i);
+ i.Next ((*op)->GetSerializedSize ());
+ }
+
+ //Padding
Peter Barnes 2013/12/26 21:25:45 Where's the END option? Isn't this required by th
+ while (optionLen % 4)
+ {
+ ++optionLen;
+ i.WriteU8 (0);
+ }
+
+ if (m_calcChecksum)
{
uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
@@ -280,8 +346,11 @@
i.WriteU16 (checksum);
}
}
-uint32_t TcpHeader::Deserialize (Buffer::Iterator start)
+
+uint32_t
+TcpHeader::Deserialize (Buffer::Iterator start)
{
+ NS_LOG_FUNCTION (this);
Buffer::Iterator i = start;
m_sourcePort = i.ReadNtohU16 ();
m_destinationPort = i.ReadNtohU16 ();
@@ -289,12 +358,36 @@
m_ackNumber = i.ReadNtohU32 ();
uint16_t field = i.ReadNtohU16 ();
m_flags = field & 0x3F;
- m_length = field>>12;
+ m_length = field >> 12;
m_windowSize = i.ReadNtohU16 ();
i.Next (2);
m_urgentPointer = i.ReadNtohU16 ();
- if(m_calcChecksum)
+ m_options.clear ();
+ unsigned optionLen = (m_length - 5) * 4;
+
+ //Re-create each option and place in m_options
+ while (optionLen)
+ {
+ uint8_t kind = i.ReadU8 ();
+ Ptr<TcpOption> op = TcpOption::CreateOption (kind);
+ optionLen -= op->Deserialize (i);
+ i.Next (op->GetSerializedSize () - 1);
+ if (op->GetKind () != 0)
+ {
+ m_options.push_back (op);
+ }
+ else
+ {
+ while (optionLen)
+ {
+ i.Next (1);
+ --optionLen;
+ }
+ }
+ }
+
+ if (m_calcChecksum)
{
uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
@@ -305,5 +398,51 @@
return GetSerializedSize ();
}
+Ptr<TcpOption>
+TcpHeader::GetOption (uint8_t kind) const
+{
+ NS_LOG_FUNCTION (this);
+ for (std::list<Ptr<TcpOption> >::const_iterator i = m_options.begin (); i != m_options.end (); ++i)
+ {
+ if ((*i)->GetKind () == kind)
+ {
+ return (*i);
+ }
+ }
+ return NULL;
+}
+
+bool
+TcpHeader::AppendOption (Ptr<TcpOption> option)
+{
+ NS_LOG_FUNCTION (this);
+ if (option->GetKind () != 0)
+ {
+ m_options.push_back (option);
+ }
+
+ // Update length
Peter Barnes 2013/12/26 21:25:45 // Length in octets (bytes), starting with the fix
+ unsigned totalLen = 20;
+ for (std::list<Ptr<TcpOption> >::iterator i = m_options.begin (); i != m_options.end (); ++i)
+ {
+ totalLen += (*i)->GetSerializedSize ();
+ }
+
+ if (totalLen - 20 > 40)
+ { // Exceeds TCP option limit of 40 bytes
+ NS_LOG_LOGIC ("Option cannot be appended because the total option length exceeds the 40 byte limit.");
+ m_options.pop_back ();
+ return false;
+ }
+
+ // Padding to align to 32 bits
Peter Barnes 2013/12/26 21:25:45 // END option and padding added in Serialize
+ if (totalLen > 20)
+ {
+ totalLen += 3;
+ }
+
+ m_length = totalLen >> 2;
Peter Barnes 2013/12/26 21:25:45 This algorithm for alignment is not obvious, since
+ return true;
+}
} // namespace ns3

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