OLD | NEW |
(Empty) | |
| 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2016 NITK Surathkal |
| 4 * |
| 5 * This program is free software; you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 2 as |
| 7 * published by the Free Software Foundation; |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software |
| 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 * |
| 18 * Authors: Shravya Ks <shravya.ks0@gmail.com> |
| 19 * |
| 20 */ |
| 21 #include "ns3/ipv4.h" |
| 22 #include "ns3/ipv6.h" |
| 23 #include "ns3/ipv4-interface-address.h" |
| 24 #include "ns3/ipv4-route.h" |
| 25 #include "ns3/ipv6-route.h" |
| 26 #include "ns3/ipv4-routing-protocol.h" |
| 27 #include "ns3/ipv6-routing-protocol.h" |
| 28 #include "../model/ipv4-end-point.h" |
| 29 #include "../model/ipv6-end-point.h" |
| 30 #include "tcp-general-test.h" |
| 31 #include "ns3/node.h" |
| 32 #include "ns3/log.h" |
| 33 #include "tcp-error-model.h" |
| 34 #include "ns3/tcp-l4-protocol.h" |
| 35 |
| 36 namespace ns3 { |
| 37 |
| 38 NS_LOG_COMPONENT_DEFINE ("TcpECNTestSuite"); |
| 39 /** |
| 40 * \ingroup internet-test |
| 41 * \ingroup tests |
| 42 * |
| 43 * \brief checks if ECT, CWR and ECE bits are set correctly in different scenari
os |
| 44 * |
| 45 * This test suite will run four combinations of enabling ECN (sender off and re
ceiver off; sender on and sender off; |
| 46 * sender off and receiver on; sender on and receiver on;) and checks that the T
OS byte of eventual packets transmitted |
| 47 * or received have ECT, CWR, and ECE set correctly (or not). It also checks if
congestion window is being reduced by half |
| 48 * only once per every window on receipt of ECE flags |
| 49 * |
| 50 */ |
| 51 class TcpECNTest : public TcpGeneralTest |
| 52 { |
| 53 public: |
| 54 /** |
| 55 * \brief Constructor |
| 56 * |
| 57 * \param testcase test case number |
| 58 * \param desc Description about the ECN capabilities of sender and reciever |
| 59 */ |
| 60 TcpECNTest (uint32_t testcase, const std::string &desc); |
| 61 |
| 62 protected: |
| 63 virtual void CWndTrace (uint32_t oldValue, uint32_t newValue); |
| 64 virtual void Rx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who); |
| 65 virtual void Tx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who); |
| 66 virtual Ptr<TcpSocketMsgBase> CreateSenderSocket (Ptr<Node> node); |
| 67 void ConfigureProperties (); |
| 68 |
| 69 private: |
| 70 uint32_t m_cwndChangeCount; |
| 71 uint32_t m_senderSent; |
| 72 uint32_t m_receiverSent; |
| 73 uint32_t m_senderReceived; |
| 74 uint32_t m_receiverReceived; |
| 75 uint32_t m_testcase; |
| 76 }; |
| 77 |
| 78 |
| 79 /** |
| 80 * \ingroup internet-test |
| 81 * \ingroup tests |
| 82 * |
| 83 * \brief A TCP socket which sends certain data packets with CE flags set for te
sts 5 and 6. |
| 84 * |
| 85 * The SendDataPacket function of this class sends data packets numbered 1 and 2
with CE flags set |
| 86 * for test 5 to verify if ECE and CWR bits are correctly set by receiver and se
nder respectively. It |
| 87 * also sets CE flags on data packets 10 and 11 in test case 6 to check if sende
r reduces congestion window |
| 88 * by half and also only once per every window. |
| 89 * |
| 90 */ |
| 91 class TcpSocketCongestedRouter : public TcpSocketMsgBase |
| 92 { |
| 93 public: |
| 94 /** |
| 95 * \brief Get the type ID. |
| 96 * \return the object TypeId |
| 97 */ |
| 98 static TypeId GetTypeId (void); |
| 99 |
| 100 uint32_t m_dataPacketSent; |
| 101 uint8_t m_testcase; |
| 102 |
| 103 TcpSocketCongestedRouter () |
| 104 : TcpSocketMsgBase () |
| 105 { |
| 106 m_dataPacketSent = 0; |
| 107 } |
| 108 |
| 109 /** |
| 110 * \brief Constructor. |
| 111 * \param other The object to copy from. |
| 112 */ |
| 113 TcpSocketCongestedRouter (const TcpSocketCongestedRouter &other) |
| 114 : TcpSocketMsgBase (other) |
| 115 { |
| 116 } |
| 117 |
| 118 void SetTestCase (uint8_t testCase); |
| 119 |
| 120 protected: |
| 121 virtual uint32_t SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool
withAck); |
| 122 virtual void ReTxTimeout (); |
| 123 Ptr<TcpSocketBase> Fork (void); |
| 124 }; |
| 125 |
| 126 NS_OBJECT_ENSURE_REGISTERED (TcpSocketCongestedRouter); |
| 127 |
| 128 TypeId |
| 129 TcpSocketCongestedRouter::GetTypeId (void) |
| 130 { |
| 131 static TypeId tid = TypeId ("ns3::TcpSocketCongestedRouter") |
| 132 .SetParent<TcpSocketMsgBase> () |
| 133 .SetGroupName ("Internet") |
| 134 .AddConstructor<TcpSocketCongestedRouter> () |
| 135 ; |
| 136 return tid; |
| 137 } |
| 138 |
| 139 void |
| 140 TcpSocketCongestedRouter::ReTxTimeout () |
| 141 { |
| 142 TcpSocketBase::ReTxTimeout (); |
| 143 } |
| 144 |
| 145 void |
| 146 TcpSocketCongestedRouter::SetTestCase (uint8_t testCase) |
| 147 { |
| 148 m_testcase = testCase; |
| 149 } |
| 150 |
| 151 uint32_t |
| 152 TcpSocketCongestedRouter::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize
, bool withAck) |
| 153 { |
| 154 NS_LOG_FUNCTION (this << seq << maxSize << withAck); |
| 155 m_dataPacketSent++; |
| 156 |
| 157 bool isRetransmission = false; |
| 158 if (seq != m_tcb->m_highTxMark) |
| 159 { |
| 160 isRetransmission = true; |
| 161 } |
| 162 |
| 163 Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq); |
| 164 uint32_t sz = p->GetSize (); // Size of packet |
| 165 uint8_t flags = withAck ? TcpHeader::ACK : 0; |
| 166 uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32
(sz)); |
| 167 |
| 168 if (withAck) |
| 169 { |
| 170 m_delAckEvent.Cancel (); |
| 171 m_delAckCount = 0; |
| 172 } |
| 173 |
| 174 // Sender should reduce the Congestion Window as a response to receiver's ECN
Echo notification only once per window |
| 175 if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get ()
> m_ecnCWRSeq.Get () && !isRetransmission ) |
| 176 { |
| 177 NS_LOG_INFO ("Backoff mechanism by reducing CWND by half because we've re
ceived ECN Echo"); |
| 178 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight
()); |
| 179 //m_tcb->m_cWnd = std::max ((uint32_t)m_tcb->m_cWnd / 2, m_tcb->m_segmentS
ize); |
| 180 m_congestionControl->ReduceCwnd (m_tcb); |
| 181 flags |= TcpHeader::CWR; |
| 182 m_ecnCWRSeq = seq; |
| 183 m_tcb->m_ecnState = TcpSocketState::ECN_CWR_SENT; |
| 184 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_
CWR_SENT"); |
| 185 NS_LOG_INFO ("CWR flags set"); |
| 186 NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] << " ->
CA_CWR"); |
| 187 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) |
| 188 { |
| 189 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_CWR
); |
| 190 m_tcb->m_congState = TcpSocketState::CA_CWR; |
| 191 } |
| 192 } |
| 193 /* |
| 194 * Add tags for each socket option. |
| 195 * Note that currently the socket adds both IPv4 tag and IPv6 tag |
| 196 * if both options are set. Once the packet got to layer three, only |
| 197 * the corresponding tags will be read. |
| 198 */ |
| 199 if (GetIpTos ()) |
| 200 { |
| 201 SocketIpTosTag ipTosTag; |
| 202 |
| 203 NS_LOG_LOGIC (" ECT bits should not be set on retransmitted packets "); |
| 204 if ( m_testcase == 5 && (m_dataPacketSent == 1 || m_dataPacketSent == 2)
&& !isRetransmission ) |
| 205 { |
| 206 ipTosTag.SetTos (GetIpTos () | 0x3); |
| 207 } |
| 208 else if ( m_testcase == 6 && ( m_dataPacketSent == 10 || m_dataPacketSent
== 11 ) && !isRetransmission ) |
| 209 { |
| 210 ipTosTag.SetTos (GetIpTos () | 0x3); |
| 211 } |
| 212 else |
| 213 { |
| 214 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && (GetIpTos ()
& 0x3) == 0 && !isRetransmission) |
| 215 { |
| 216 ipTosTag.SetTos (GetIpTos () | 0x2); |
| 217 } |
| 218 else |
| 219 { |
| 220 ipTosTag.SetTos (GetIpTos ()); |
| 221 } |
| 222 } |
| 223 p->AddPacketTag (ipTosTag); |
| 224 } |
| 225 else |
| 226 { |
| 227 SocketIpTosTag ipTosTag; |
| 228 if ( m_testcase == 5 && (m_dataPacketSent == 1 || m_dataPacketSent == 2)
&& !isRetransmission) |
| 229 { |
| 230 ipTosTag.SetTos (0x3); |
| 231 } |
| 232 else if ( m_testcase == 6 && ( m_dataPacketSent == 10 || m_dataPacketSent
== 11 ) && !isRetransmission ) |
| 233 { |
| 234 ipTosTag.SetTos (0x3); |
| 235 } |
| 236 else |
| 237 { |
| 238 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && !isRetransmis
sion) |
| 239 { |
| 240 ipTosTag.SetTos (0x2); |
| 241 } |
| 242 } |
| 243 p->AddPacketTag (ipTosTag); |
| 244 } |
| 245 |
| 246 if (IsManualIpv6Tclass ()) |
| 247 { |
| 248 SocketIpv6TclassTag ipTclassTag; |
| 249 if ( m_testcase == 5 && (m_dataPacketSent == 1 || m_dataPacketSent == 2)
&& !isRetransmission ) |
| 250 { |
| 251 ipTclassTag.SetTclass (GetIpv6Tclass () | 0x3); |
| 252 } |
| 253 else if ( m_testcase == 6 && ( m_dataPacketSent == 10 || m_dataPacketSent
== 11 ) && !isRetransmission) |
| 254 { |
| 255 ipTclassTag.SetTclass (GetIpv6Tclass () | 0x3); |
| 256 } |
| 257 else |
| 258 { |
| 259 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && (GetIpv6Tclas
s () & 0x3) == 0 && !isRetransmission) |
| 260 { |
| 261 ipTclassTag.SetTclass (GetIpv6Tclass () | 0x2); |
| 262 } |
| 263 else |
| 264 { |
| 265 ipTclassTag.SetTclass (GetIpv6Tclass ()); |
| 266 } |
| 267 } |
| 268 p->AddPacketTag (ipTclassTag); |
| 269 } |
| 270 else |
| 271 { |
| 272 SocketIpv6TclassTag ipTclassTag; |
| 273 if ( m_testcase == 5 && (m_dataPacketSent == 1 || m_dataPacketSent == 2)
&& !isRetransmission) |
| 274 { |
| 275 ipTclassTag.SetTclass (0x3); |
| 276 } |
| 277 else if ( m_testcase == 6 &&( m_dataPacketSent == 10 || m_dataPacketSent =
= 11 ) && !isRetransmission) |
| 278 { |
| 279 ipTclassTag.SetTclass (0x3); |
| 280 } |
| 281 else |
| 282 { |
| 283 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && !isRetransmis
sion) |
| 284 { |
| 285 ipTclassTag.SetTclass (0x2); |
| 286 } |
| 287 } |
| 288 p->AddPacketTag (ipTclassTag); |
| 289 } |
| 290 |
| 291 if (IsManualIpTtl ()) |
| 292 { |
| 293 SocketIpTtlTag ipTtlTag; |
| 294 ipTtlTag.SetTtl (GetIpTtl ()); |
| 295 p->AddPacketTag (ipTtlTag); |
| 296 } |
| 297 |
| 298 if (IsManualIpv6HopLimit ()) |
| 299 { |
| 300 SocketIpv6HopLimitTag ipHopLimitTag; |
| 301 ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ()); |
| 302 p->AddPacketTag (ipHopLimitTag); |
| 303 } |
| 304 |
| 305 uint8_t priority = GetPriority (); |
| 306 if (priority) |
| 307 { |
| 308 SocketPriorityTag priorityTag; |
| 309 priorityTag.SetPriority (priority); |
| 310 p->ReplacePacketTag (priorityTag); |
| 311 } |
| 312 |
| 313 if (m_closeOnEmpty && (remainingData == 0)) |
| 314 { |
| 315 flags |= TcpHeader::FIN; |
| 316 if (m_state == ESTABLISHED) |
| 317 { // On active close: I am the first one to send FIN |
| 318 NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1"); |
| 319 m_state = FIN_WAIT_1; |
| 320 } |
| 321 else if (m_state == CLOSE_WAIT) |
| 322 { // On passive close: Peer sent me FIN already |
| 323 NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK"); |
| 324 m_state = LAST_ACK; |
| 325 } |
| 326 } |
| 327 TcpHeader header; |
| 328 header.SetFlags (flags); |
| 329 header.SetSequenceNumber (seq); |
| 330 header.SetAckNumber (m_rxBuffer->NextRxSequence ()); |
| 331 if (m_endPoint) |
| 332 { |
| 333 header.SetSourcePort (m_endPoint->GetLocalPort ()); |
| 334 header.SetDestinationPort (m_endPoint->GetPeerPort ()); |
| 335 } |
| 336 else |
| 337 { |
| 338 header.SetSourcePort (m_endPoint6->GetLocalPort ()); |
| 339 header.SetDestinationPort (m_endPoint6->GetPeerPort ()); |
| 340 } |
| 341 header.SetWindowSize (AdvertisedWindowSize ()); |
| 342 AddOptions (header); |
| 343 |
| 344 if (m_retxEvent.IsExpired ()) |
| 345 { |
| 346 // Schedules retransmit timeout. m_rto should be already doubled. |
| 347 |
| 348 NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " << |
| 349 Simulator::Now ().GetSeconds () << " to expire at time " << |
| 350 (Simulator::Now () + m_rto.Get ()).GetSeconds () ); |
| 351 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketCongestedRouter::ReTxT
imeout, this); |
| 352 } |
| 353 |
| 354 m_txTrace (p, header, this); |
| 355 |
| 356 if (m_endPoint) |
| 357 { |
| 358 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), |
| 359 m_endPoint->GetPeerAddress (), m_boundnetdevice); |
| 360 NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " << |
| 361 remainingData << " via TcpL4Protocol to " << m_endPoint->Ge
tPeerAddress () << |
| 362 ". Header " << header); |
| 363 } |
| 364 else |
| 365 { |
| 366 m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (), |
| 367 m_endPoint6->GetPeerAddress (), m_boundnetdevice); |
| 368 NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " << |
| 369 remainingData << " via TcpL4Protocol to " << m_endPoint6->G
etPeerAddress () << |
| 370 ". Header " << header); |
| 371 } |
| 372 |
| 373 UpdateRttHistory (seq, sz, isRetransmission); |
| 374 |
| 375 // Notify the application of the data being sent unless this is a retransmit |
| 376 if (seq + sz > m_tcb->m_highTxMark) |
| 377 { |
| 378 Simulator::ScheduleNow (&TcpSocketCongestedRouter::NotifyDataSent, this, |
| 379 (seq + sz - m_tcb->m_highTxMark.Get ())); |
| 380 } |
| 381 // Update highTxMark |
| 382 m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ()); |
| 383 return sz; |
| 384 } |
| 385 |
| 386 Ptr<TcpSocketBase> |
| 387 TcpSocketCongestedRouter::Fork (void) |
| 388 { |
| 389 return CopyObject<TcpSocketCongestedRouter> (this); |
| 390 } |
| 391 |
| 392 |
| 393 TcpECNTest::TcpECNTest (uint32_t testcase, const std::string &desc) |
| 394 : TcpGeneralTest (desc), |
| 395 m_cwndChangeCount (0), |
| 396 m_senderSent (0), |
| 397 m_receiverSent (0), |
| 398 m_senderReceived (0), |
| 399 m_receiverReceived (0), |
| 400 m_testcase (testcase) |
| 401 { |
| 402 } |
| 403 |
| 404 void |
| 405 TcpECNTest::ConfigureProperties () |
| 406 { |
| 407 TcpGeneralTest::ConfigureProperties (); |
| 408 if (m_testcase == 2 || m_testcase == 4 || m_testcase == 5 || m_testcase == 6) |
| 409 { |
| 410 SetEcn (SENDER); |
| 411 } |
| 412 if (m_testcase == 3 || m_testcase == 4 ||m_testcase == 5 || m_testcase == 6) |
| 413 { |
| 414 SetEcn (RECEIVER); |
| 415 } |
| 416 } |
| 417 |
| 418 void |
| 419 TcpECNTest::CWndTrace (uint32_t oldValue, uint32_t newValue) |
| 420 { |
| 421 if (m_testcase == 6) |
| 422 { |
| 423 uint32_t increase = newValue - oldValue; |
| 424 if ( increase < 0) |
| 425 { |
| 426 m_cwndChangeCount++; |
| 427 NS_TEST_ASSERT_MSG_EQ (m_cwndChangeCount, 1, "Congestion window should
be reduced once per every window"); |
| 428 NS_TEST_ASSERT_MSG_EQ (newValue, oldValue / 2, "Congestion window shou
ld be reduced by half"); |
| 429 } |
| 430 } |
| 431 } |
| 432 |
| 433 void |
| 434 TcpECNTest::Rx (const Ptr<const Packet> p, const TcpHeader &h, SocketWho who) |
| 435 { |
| 436 if (who == RECEIVER) |
| 437 { |
| 438 if (m_receiverReceived == 0) |
| 439 { |
| 440 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::SYN), 0, "SYN sho
uld be received as first message at the receiver"); |
| 441 if (m_testcase == 2 || m_testcase == 4 || m_testcase == 5 ||m_testcase
== 6) |
| 442 { |
| 443 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::ECE) && ((h.G
etFlags ()) & TcpHeader::CWR), 0, "The flags ECE + CWR should be set in the TCP
header of first message receieved at receiver when sender is ECN Capable"); |
| 444 } |
| 445 else |
| 446 { |
| 447 NS_TEST_ASSERT_MSG_EQ (((h.GetFlags ()) & TcpHeader::ECE) && ((h.G
etFlags ()) & TcpHeader::CWR), 0, "The flags ECE + CWR should not be set in the
TCP header of first message receieved at receiver when sender is not ECN Capable
"); |
| 448 } |
| 449 } |
| 450 else if (m_receiverReceived == 1) |
| 451 { |
| 452 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::ACK), 0, "ACK sho
uld be received as second message at receiver"); |
| 453 } |
| 454 else if (m_receiverReceived == 3 && m_testcase == 5) |
| 455 { |
| 456 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::CWR), 0, "Sender
should send CWR on receipt of ECE"); |
| 457 } |
| 458 m_receiverReceived++; |
| 459 } |
| 460 else if (who == SENDER) |
| 461 { |
| 462 if (m_senderReceived == 0) |
| 463 { |
| 464 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::SYN) && ((h.GetFl
ags ()) & TcpHeader::ACK), 0, "SYN+ACK received as first message at sender"); |
| 465 if (m_testcase == 4 || m_testcase == 5 || m_testcase == 6) |
| 466 { |
| 467 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::ECE), 0, "The
flag ECE should be set in the TCP header of first message receieved at sender w
hen both receiver and sender are ECN Capable"); |
| 468 } |
| 469 else |
| 470 { |
| 471 NS_TEST_ASSERT_MSG_EQ (((h.GetFlags ()) & TcpHeader::ECE), 0, "The
flag ECE should not be set in the TCP header of first message receieved at send
er when either receiver or sender are not ECN Capable"); |
| 472 } |
| 473 } |
| 474 if (m_senderReceived == 3 && m_testcase == 5) |
| 475 { |
| 476 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::ECE), 0, "The fla
g ECE should be set in TCP header of the packet sent by the receiver when it rec
eives a packet with CE bit set in IP header"); |
| 477 } |
| 478 if (m_senderReceived == 4 && m_testcase == 5) |
| 479 { |
| 480 NS_TEST_ASSERT_MSG_NE (((h.GetFlags ()) & TcpHeader::ECE), 0, "The fla
g ECE should be set in TCP header of the packet sent by the receiver even after
sender sends CWR flags to receiver if it receives a packet with CE bit set in IP
header"); |
| 481 } |
| 482 if ( m_testcase == 5 && m_receiverReceived > 12) |
| 483 { |
| 484 NS_TEST_ASSERT_MSG_EQ (((h.GetFlags ()) & TcpHeader::ECE), 0, "The fla
g ECE should not be set in TCP header of the packet sent by the receiver after s
ender sends CWR flags to receiver and receiver receives a packet without CE bit
set in IP header"); |
| 485 } |
| 486 m_senderReceived++; |
| 487 } |
| 488 } |
| 489 |
| 490 void |
| 491 TcpECNTest::Tx (const Ptr<const Packet> p, const TcpHeader &h, SocketWho who) |
| 492 { |
| 493 if (who == SENDER) |
| 494 { |
| 495 m_senderSent++; |
| 496 if (m_senderSent == 3) |
| 497 { |
| 498 SocketIpTosTag ipTosTag; |
| 499 p->PeekPacketTag (ipTosTag); |
| 500 if (m_testcase == 4 || m_testcase == 6) |
| 501 { |
| 502 NS_TEST_ASSERT_MSG_EQ ((ipTosTag.GetTos ()), 0x2, "IP TOS should h
ave ECT set if ECN negotiation between endpoints is successful"); |
| 503 } |
| 504 else if (m_testcase == 5) |
| 505 { |
| 506 if (m_senderSent == 3 || m_senderSent == 4) |
| 507 { |
| 508 NS_TEST_ASSERT_MSG_EQ ((ipTosTag.GetTos ()), 0x3, "IP TOS shou
ld have CE bit set for 3rd and 4th packet sent in test case 5"); |
| 509 } |
| 510 else |
| 511 { |
| 512 NS_TEST_ASSERT_MSG_EQ ((ipTosTag.GetTos ()), 0x2, "IP TOS shou
ld have ECT set if ECN negotiation between endpoints is successful"); |
| 513 } |
| 514 } |
| 515 else |
| 516 { |
| 517 NS_TEST_ASSERT_MSG_NE ((ipTosTag.GetTos ()), 0x2, "IP TOS should n
ot have ECT set if ECN negotiation between endpoints is unsuccessful"); |
| 518 } |
| 519 } |
| 520 } |
| 521 } |
| 522 |
| 523 Ptr<TcpSocketMsgBase> |
| 524 TcpECNTest::CreateSenderSocket (Ptr<Node> node) |
| 525 { |
| 526 if (m_testcase == 5 || m_testcase == 6) |
| 527 { |
| 528 Ptr<TcpSocketCongestedRouter> socket = DynamicCast<TcpSocketCongestedRoute
r> ( |
| 529 CreateSocket (node, |
| 530 TcpSocketCongestedRouter::GetTypeId (), |
| 531 m_congControlTypeId)); |
| 532 socket->SetTestCase (m_testcase); |
| 533 return socket; |
| 534 } |
| 535 else |
| 536 { |
| 537 return TcpGeneralTest::CreateSenderSocket (node); |
| 538 } |
| 539 } |
| 540 |
| 541 /** |
| 542 * \ingroup internet-test |
| 543 * \ingroup tests |
| 544 * |
| 545 * \brief TCP ECN TestSuite |
| 546 */ |
| 547 static class TcpECNTestSuite : public TestSuite |
| 548 { |
| 549 public: |
| 550 TcpECNTestSuite () : TestSuite ("tcp-ecn-test", UNIT) |
| 551 { |
| 552 AddTestCase (new TcpECNTest (1, "ECN Negotiation Test : ECN incapable sender
and ECN incapable receiver"), |
| 553 TestCase::QUICK); |
| 554 AddTestCase (new TcpECNTest (2, "ECN Negotiation Test : ECN capable sender a
nd ECN incapable receiver"), |
| 555 TestCase::QUICK); |
| 556 AddTestCase (new TcpECNTest (3, "ECN Negotiation Test : ECN incapable sender
and ECN capable receiver"), |
| 557 TestCase::QUICK); |
| 558 AddTestCase (new TcpECNTest (4, "ECN Negotiation Test : ECN capable sender a
nd ECN capable receiver"), |
| 559 TestCase::QUICK); |
| 560 AddTestCase (new TcpECNTest (5, "ECE and CWR Functionality Test: ECN capable
sender and ECN capable receiver"), |
| 561 TestCase::QUICK); |
| 562 AddTestCase (new TcpECNTest (6, "Congestion Window Reduction Test :ECN capab
le sender and ECN capable receiver"), |
| 563 TestCase::QUICK); |
| 564 } |
| 565 } g_tcpECNTestSuite; |
| 566 |
| 567 } // namespace ns3 |
OLD | NEW |