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