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 |