1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Adrian Sai-wah Tam
4  * Copyright (c) 2015 ResiliNets, ITTC, University of Kansas
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Original Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
20  * Documentation, test cases: Truc Anh N. Nguyen   <annguyen@ittc.ku.edu>
21  *                            ResiliNets Research Group   http://wiki.ittc.ku.edu/resilinets
22  *                            The University of Kansas
23  *                            James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
24  */
25 
26 #include "tcp-option-sack.h"
27 #include "ns3/log.h"
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("TcpOptionSack");
32 
33 NS_OBJECT_ENSURE_REGISTERED (TcpOptionSack);
34 
TcpOptionSack()35 TcpOptionSack::TcpOptionSack ()
36   : TcpOption ()
37 {
38 }
39 
~TcpOptionSack()40 TcpOptionSack::~TcpOptionSack ()
41 {
42 }
43 
44 TypeId
GetTypeId(void)45 TcpOptionSack::GetTypeId (void)
46 {
47   static TypeId tid = TypeId ("ns3::TcpOptionSack")
48     .SetParent<TcpOption> ()
49     .SetGroupName ("Internet")
50     .AddConstructor<TcpOptionSack> ()
51   ;
52   return tid;
53 }
54 
55 TypeId
GetInstanceTypeId(void) const56 TcpOptionSack::GetInstanceTypeId (void) const
57 {
58   return GetTypeId ();
59 }
60 
61 void
Print(std::ostream & os) const62 TcpOptionSack::Print (std::ostream &os) const
63 {
64   os << "blocks: " << GetNumSackBlocks () << ",";
65   for (SackList::const_iterator it = m_sackList.begin (); it != m_sackList.end (); ++it)
66     {
67       os << "[" << it->first << "," << it->second << "]";
68     }
69 }
70 
71 uint32_t
GetSerializedSize(void) const72 TcpOptionSack::GetSerializedSize (void) const
73 {
74   NS_LOG_FUNCTION (this);
75   NS_LOG_LOGIC ("Serialized size: " << 2 + GetNumSackBlocks () * 8);
76   return 2 + GetNumSackBlocks () * 8;
77 }
78 
79 void
Serialize(Buffer::Iterator start) const80 TcpOptionSack::Serialize (Buffer::Iterator start) const
81 {
82   NS_LOG_FUNCTION (this);
83   Buffer::Iterator i = start;
84   i.WriteU8 (GetKind ()); // Kind
85   uint8_t length = static_cast<uint8_t> (GetNumSackBlocks () * 8 + 2);
86   i.WriteU8 (length); // Length
87 
88   for (SackList::const_iterator it = m_sackList.begin (); it != m_sackList.end (); ++it)
89     {
90       SequenceNumber32 leftEdge = it->first;
91       SequenceNumber32 rightEdge = it->second;
92       i.WriteHtonU32 (leftEdge.GetValue ());   // Left edge of the block
93       i.WriteHtonU32 (rightEdge.GetValue ());  // Right edge of the block
94     }
95 }
96 
97 uint32_t
Deserialize(Buffer::Iterator start)98 TcpOptionSack::Deserialize (Buffer::Iterator start)
99 {
100   NS_LOG_FUNCTION (this);
101   Buffer::Iterator i = start;
102   uint8_t readKind = i.ReadU8 ();
103   if (readKind != GetKind ())
104     {
105       NS_LOG_WARN ("Malformed SACK option, wrong type");
106       return 0;
107     }
108 
109   uint8_t size = i.ReadU8 ();
110   NS_LOG_LOGIC ("Size: " << static_cast<uint32_t> (size));
111   m_sackList.clear ();
112   uint8_t sackCount = (size - 2) / 8;
113   while (sackCount)
114     {
115       SequenceNumber32 leftEdge = SequenceNumber32 (i.ReadNtohU32 ());
116       SequenceNumber32 rightEdge = SequenceNumber32 (i.ReadNtohU32 ());
117       SackBlock s (leftEdge, rightEdge);
118       AddSackBlock (s);
119       sackCount--;
120     }
121 
122   return GetSerializedSize ();
123 }
124 
125 uint8_t
GetKind(void) const126 TcpOptionSack::GetKind (void) const
127 {
128   return TcpOption::SACK;
129 }
130 
131 void
AddSackBlock(SackBlock s)132 TcpOptionSack::AddSackBlock (SackBlock s)
133 {
134   NS_LOG_FUNCTION (this);
135   m_sackList.push_back (s);
136 }
137 
138 uint32_t
GetNumSackBlocks(void) const139 TcpOptionSack::GetNumSackBlocks (void) const
140 {
141   NS_LOG_FUNCTION (this);
142   NS_LOG_LOGIC ("Number of SACK blocks appended: " << m_sackList.size ());
143   return static_cast<uint32_t> (m_sackList.size ());
144 }
145 
146 void
ClearSackList(void)147 TcpOptionSack::ClearSackList (void)
148 {
149   m_sackList.clear ();
150 }
151 
152 TcpOptionSack::SackList
GetSackList(void) const153 TcpOptionSack::GetSackList (void) const
154 {
155   NS_LOG_FUNCTION (this);
156   return m_sackList;
157 }
158 
159 std::ostream &
operator <<(std::ostream & os,TcpOptionSack const & sackOption)160 operator<< (std::ostream & os, TcpOptionSack const & sackOption)
161 {
162   std::stringstream ss;
163   ss << "{";
164   for (auto it = sackOption.m_sackList.begin (); it != sackOption.m_sackList.end (); ++it)
165     {
166       ss << *it;
167     }
168   ss << "}";
169   os << ss.str ();
170   return os;
171 }
172 
173 std::ostream &
operator <<(std::ostream & os,TcpOptionSack::SackBlock const & sackBlock)174 operator<< (std::ostream & os, TcpOptionSack::SackBlock const & sackBlock)
175 {
176   std::stringstream ss;
177   ss << "[" << sackBlock.first << ";" << sackBlock.second << "]";
178   os << ss.str ();
179   return os;
180 }
181 
182 } // namespace ns3
183