|
Lines 91-97
TcpSocketBase::GetTypeId (void)
|
Link Here
|
|---|
|
| 91 |
MakeCallbackChecker ()) |
91 |
MakeCallbackChecker ()) |
| 92 |
.AddAttribute ("WindowScaling", "Enable or disable Window Scaling option", |
92 |
.AddAttribute ("WindowScaling", "Enable or disable Window Scaling option", |
| 93 |
BooleanValue (true), |
93 |
BooleanValue (true), |
| 94 |
MakeBooleanAccessor (&TcpSocketBase::m_winScalingEnabled), |
94 |
MakeBooleanAccessor (&TcpSocketBase::EnableWSOption, |
|
|
95 |
&TcpSocketBase::GetWSOptionEnabled), |
| 95 |
MakeBooleanChecker ()) |
96 |
MakeBooleanChecker ()) |
| 96 |
.AddAttribute ("Timestamp", "Enable or disable Timestamp option", |
97 |
.AddAttribute ("Timestamp", "Enable or disable Timestamp option", |
| 97 |
BooleanValue (true), |
98 |
BooleanValue (true), |
|
Lines 284-290
TcpSocketBase::TcpSocketBase (void)
|
Link Here
|
|---|
|
| 284 |
m_highRxMark (0), |
285 |
m_highRxMark (0), |
| 285 |
m_highRxAckMark (0), |
286 |
m_highRxAckMark (0), |
| 286 |
m_bytesAckedNotProcessed (0), |
287 |
m_bytesAckedNotProcessed (0), |
| 287 |
m_winScalingEnabled (false), |
288 |
m_winScalingEnabled (0), |
| 288 |
m_rcvWindShift (0), |
289 |
m_rcvWindShift (0), |
| 289 |
m_sndWindShift (0), |
290 |
m_sndWindShift (0), |
| 290 |
m_timestampEnabled (true), |
291 |
m_timestampEnabled (true), |
|
Lines 1164-1171
TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
|
Link Here
|
|---|
|
| 1164 |
|
1165 |
|
| 1165 |
m_rxTrace (packet, tcpHeader, this); |
1166 |
m_rxTrace (packet, tcpHeader, this); |
| 1166 |
|
1167 |
|
| 1167 |
ReadOptions (tcpHeader); |
|
|
| 1168 |
|
| 1169 |
if (tcpHeader.GetFlags () & TcpHeader::SYN) |
1168 |
if (tcpHeader.GetFlags () & TcpHeader::SYN) |
| 1170 |
{ |
1169 |
{ |
| 1171 |
/* The window field in a segment where the SYN bit is set (i.e., a <SYN> |
1170 |
/* The window field in a segment where the SYN bit is set (i.e., a <SYN> |
|
Lines 1174-1194
TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
|
Link Here
|
|---|
|
| 1174 |
*/ |
1173 |
*/ |
| 1175 |
m_rWnd = tcpHeader.GetWindowSize (); |
1174 |
m_rWnd = tcpHeader.GetWindowSize (); |
| 1176 |
|
1175 |
|
| 1177 |
if (m_tcb->m_initialSsThresh == UINT32_MAX) |
1176 |
/* RFC 7323, Section 2.2 |
|
|
1177 |
* |
| 1178 |
* "If a Window Scale option was received in the initial <SYN> segment, |
| 1179 |
* then this option MAY be sent in the <SYN,ACK> segment." |
| 1180 |
* |
| 1181 |
* RFC 7323, Section 2.3 |
| 1182 |
* |
| 1183 |
* "If a TCP receives a <SYN> segment containing a Window Scale |
| 1184 |
* option, it SHOULD send its own Window Scale option in the |
| 1185 |
* <SYN,ACK> segment." |
| 1186 |
* |
| 1187 |
* RFC is incostistent in case a <SYN> contains WS option, but the |
| 1188 |
* user disabled it through Attributes. |
| 1189 |
* As choice, we use the latter approach, enabling WS but advertising |
| 1190 |
* 1 as shift, regardless of the buffer size (and doing so we pratically |
| 1191 |
* disable the window scale, keeping the send of the option) |
| 1192 |
*/ |
| 1193 |
if (tcpHeader.HasOption (TcpOption::WINSCALE)) |
| 1178 |
{ |
1194 |
{ |
| 1179 |
m_tcb->m_initialSsThresh = m_rWnd << m_sndWindShift; |
1195 |
ProcessOptionWScale (tcpHeader.GetOption (TcpOption::WINSCALE)); |
|
|
1196 |
|
| 1197 |
if (tcpHeader.GetFlags () == TcpHeader::SYN && m_winScalingEnabled == 0) |
| 1198 |
{ |
| 1199 |
// This is a plain <SYN> with WS enabled, but users choice is |
| 1200 |
// to disable our WS side. <SYN-ACK> will have WS option with shift = 1 |
| 1201 |
m_winScalingEnabled = 2; |
| 1202 |
} |
| 1203 |
|
| 1204 |
if (m_tcb->m_initialSsThresh == UINT32_MAX) |
| 1205 |
{ |
| 1206 |
m_tcb->m_initialSsThresh = m_rWnd << m_sndWindShift; |
| 1207 |
} |
| 1208 |
} |
| 1209 |
else |
| 1210 |
{ |
| 1211 |
// Disable window scaling at all; our peer does not support it. |
| 1212 |
m_winScalingEnabled = 0; |
| 1213 |
} |
| 1214 |
|
| 1215 |
// When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end |
| 1216 |
if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled) |
| 1217 |
{ |
| 1218 |
ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS)); |
| 1219 |
} |
| 1220 |
else |
| 1221 |
{ |
| 1222 |
m_timestampEnabled = false; |
| 1180 |
} |
1223 |
} |
| 1181 |
|
1224 |
|
|
|
1225 |
// Initialize cWnd and ssThresh |
| 1182 |
m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize (); |
1226 |
m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize (); |
| 1183 |
m_tcb->m_ssThresh = GetInitialSSThresh (); |
1227 |
m_tcb->m_ssThresh = GetInitialSSThresh (); |
| 1184 |
} |
1228 |
} |
| 1185 |
else if (tcpHeader.GetFlags () & TcpHeader::ACK) |
1229 |
else if (tcpHeader.GetFlags () & TcpHeader::ACK) |
| 1186 |
{ |
1230 |
{ |
|
|
1231 |
if (m_timestampEnabled) |
| 1232 |
{ |
| 1233 |
if (tcpHeader.HasOption (TcpOption::TS)) |
| 1234 |
{ |
| 1235 |
ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS)); |
| 1236 |
} |
| 1237 |
else |
| 1238 |
{ |
| 1239 |
NS_LOG_LOGIC ("At state " << TcpStateName[m_state] << |
| 1240 |
" received packet of seq [" << seq << |
| 1241 |
":" << seq + packet->GetSize () << |
| 1242 |
") without TS option. Silently discard it"); |
| 1243 |
return; |
| 1244 |
} |
| 1245 |
} |
| 1246 |
|
| 1187 |
EstimateRtt (tcpHeader); |
1247 |
EstimateRtt (tcpHeader); |
| 1188 |
UpdateWindowSize (tcpHeader); |
1248 |
UpdateWindowSize (tcpHeader); |
| 1189 |
} |
1249 |
} |
| 1190 |
|
1250 |
|
| 1191 |
|
|
|
| 1192 |
if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ()) |
1251 |
if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ()) |
| 1193 |
{ // Zero window: Enter persist state to send 1 byte to probe |
1252 |
{ // Zero window: Enter persist state to send 1 byte to probe |
| 1194 |
NS_LOG_LOGIC (this << " Enter zerowindow persist state"); |
1253 |
NS_LOG_LOGIC (this << " Enter zerowindow persist state"); |
|
Lines 3079-3119
TcpSocketBase::GetAllowBroadcast (void) const
|
Link Here
|
|---|
|
| 3079 |
} |
3138 |
} |
| 3080 |
|
3139 |
|
| 3081 |
void |
3140 |
void |
| 3082 |
TcpSocketBase::ReadOptions (const TcpHeader& header) |
|
|
| 3083 |
{ |
| 3084 |
NS_LOG_FUNCTION (this << header); |
| 3085 |
|
| 3086 |
if ((header.GetFlags () & TcpHeader::SYN)) |
| 3087 |
{ |
| 3088 |
if (m_winScalingEnabled) |
| 3089 |
{ |
| 3090 |
m_winScalingEnabled = false; |
| 3091 |
|
| 3092 |
if (header.HasOption (TcpOption::WINSCALE)) |
| 3093 |
{ |
| 3094 |
m_winScalingEnabled = true; |
| 3095 |
ProcessOptionWScale (header.GetOption (TcpOption::WINSCALE)); |
| 3096 |
} |
| 3097 |
} |
| 3098 |
} |
| 3099 |
|
| 3100 |
bool timestampAttribute = m_timestampEnabled; |
| 3101 |
m_timestampEnabled = false; |
| 3102 |
|
| 3103 |
if (header.HasOption (TcpOption::TS) && timestampAttribute) |
| 3104 |
{ |
| 3105 |
m_timestampEnabled = true; |
| 3106 |
ProcessOptionTimestamp (header.GetOption (TcpOption::TS)); |
| 3107 |
} |
| 3108 |
} |
| 3109 |
|
| 3110 |
void |
| 3111 |
TcpSocketBase::AddOptions (TcpHeader& header) |
3141 |
TcpSocketBase::AddOptions (TcpHeader& header) |
| 3112 |
{ |
3142 |
{ |
| 3113 |
NS_LOG_FUNCTION (this << header); |
3143 |
NS_LOG_FUNCTION (this << header); |
| 3114 |
|
3144 |
|
| 3115 |
// The window scaling option is set only on SYN packets |
3145 |
// The window scaling option is set only on SYN packets |
| 3116 |
if (m_winScalingEnabled && (header.GetFlags () & TcpHeader::SYN)) |
3146 |
if ((header.GetFlags () & TcpHeader::SYN) && m_winScalingEnabled > 0) |
| 3117 |
{ |
3147 |
{ |
| 3118 |
AddOptionWScale (header); |
3148 |
AddOptionWScale (header); |
| 3119 |
} |
3149 |
} |
|
Lines 3170-3175
TcpSocketBase::CalculateWScale () const
|
Link Here
|
|---|
|
| 3170 |
} |
3200 |
} |
| 3171 |
|
3201 |
|
| 3172 |
void |
3202 |
void |
|
|
3203 |
TcpSocketBase::EnableWSOption (bool enable) |
| 3204 |
{ |
| 3205 |
if (enable) |
| 3206 |
{ |
| 3207 |
m_winScalingEnabled = 1; |
| 3208 |
} |
| 3209 |
else |
| 3210 |
{ |
| 3211 |
m_winScalingEnabled = 0; |
| 3212 |
} |
| 3213 |
} |
| 3214 |
|
| 3215 |
bool |
| 3216 |
TcpSocketBase::GetWSOptionEnabled (void) const |
| 3217 |
{ |
| 3218 |
return m_winScalingEnabled == 1; |
| 3219 |
} |
| 3220 |
|
| 3221 |
void |
| 3173 |
TcpSocketBase::AddOptionWScale (TcpHeader &header) |
3222 |
TcpSocketBase::AddOptionWScale (TcpHeader &header) |
| 3174 |
{ |
3223 |
{ |
| 3175 |
NS_LOG_FUNCTION (this << header); |
3224 |
NS_LOG_FUNCTION (this << header); |
|
Lines 3177-3186
TcpSocketBase::AddOptionWScale (TcpHeader &header)
|
Link Here
|
|---|
|
| 3177 |
|
3226 |
|
| 3178 |
Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> (); |
3227 |
Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> (); |
| 3179 |
|
3228 |
|
| 3180 |
// In naming, we do the contrary of RFC 1323. The sended scaling factor |
3229 |
if (m_winScalingEnabled == 2) |
| 3181 |
// is Snd.Wind.Scale (and not Rcv.Wind.Scale) |
3230 |
{ |
|
|
3231 |
m_rcvWindShift = 1; |
| 3232 |
} |
| 3233 |
else |
| 3234 |
{ |
| 3235 |
m_rcvWindShift = CalculateWScale (); |
| 3236 |
} |
| 3182 |
|
3237 |
|
| 3183 |
m_rcvWindShift = CalculateWScale (); |
|
|
| 3184 |
option->SetScale (m_rcvWindShift); |
3238 |
option->SetScale (m_rcvWindShift); |
| 3185 |
|
3239 |
|
| 3186 |
header.AppendOption (option); |
3240 |
header.AppendOption (option); |