OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/quic_sent_packet_manager.h" | 5 #include "net/quic/quic_sent_packet_manager.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "net/quic/congestion_control/pacing_sender.h" | 9 #include "net/quic/congestion_control/pacing_sender.h" |
10 #include "net/quic/quic_ack_notifier_manager.h" | 10 #include "net/quic/quic_ack_notifier_manager.h" |
11 | 11 |
12 using std::make_pair; | 12 using std::make_pair; |
13 using std::max; | 13 using std::max; |
14 using std::min; | 14 using std::min; |
15 | 15 |
16 // TODO(rtenneti): Remove this. | 16 // TODO(rtenneti): Remove this. |
17 // Do not flip this flag until the flakiness of the | 17 // Do not flip this flag until the flakiness of the |
18 // net/tools/quic/end_to_end_test is fixed. | 18 // net/tools/quic/end_to_end_test is fixed. |
19 // If true, then QUIC connections will track the retransmission history of a | 19 // If true, then QUIC connections will track the retransmission history of a |
20 // packet so that an ack of a previous transmission will ack the data of all | 20 // packet so that an ack of a previous transmission will ack the data of all |
21 // other transmissions. | 21 // other transmissions. |
22 bool FLAGS_track_retransmission_history = false; | 22 bool FLAGS_track_retransmission_history = false; |
23 | 23 |
24 // A test-only flag to prevent the RTO from backing off when multiple sequential | |
25 // tail drops occur. | |
26 bool FLAGS_limit_rto_increase_for_tests = false; | |
27 | |
28 // Do not remove this flag until the Finch-trials described in b/11706275 | 24 // Do not remove this flag until the Finch-trials described in b/11706275 |
29 // are complete. | 25 // are complete. |
30 // If true, QUIC connections will support the use of a pacing algorithm when | 26 // If true, QUIC connections will support the use of a pacing algorithm when |
31 // sending packets, in an attempt to reduce packet loss. The client must also | 27 // sending packets, in an attempt to reduce packet loss. The client must also |
32 // request pacing for the server to enable it. | 28 // request pacing for the server to enable it. |
33 bool FLAGS_enable_quic_pacing = false; | 29 bool FLAGS_enable_quic_pacing = false; |
34 | 30 |
35 namespace net { | 31 namespace net { |
36 namespace { | 32 namespace { |
37 static const int kBitrateSmoothingPeriodMs = 1000; | 33 static const int kBitrateSmoothingPeriodMs = 1000; |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 void QuicSentPacketManager::ClearPreviousRetransmissions(size_t num_to_clear) { | 248 void QuicSentPacketManager::ClearPreviousRetransmissions(size_t num_to_clear) { |
253 UnackedPacketMap::iterator it = unacked_packets_.begin(); | 249 UnackedPacketMap::iterator it = unacked_packets_.begin(); |
254 while (it != unacked_packets_.end() && num_to_clear > 0) { | 250 while (it != unacked_packets_.end() && num_to_clear > 0) { |
255 QuicPacketSequenceNumber sequence_number = it->first; | 251 QuicPacketSequenceNumber sequence_number = it->first; |
256 // If this is not a previous transmission then there is no point | 252 // If this is not a previous transmission then there is no point |
257 // in clearing out any further packets, because it will not affect | 253 // in clearing out any further packets, because it will not affect |
258 // the high water mark. | 254 // the high water mark. |
259 SequenceNumberSet* previous_transmissions = | 255 SequenceNumberSet* previous_transmissions = |
260 it->second.previous_transmissions; | 256 it->second.previous_transmissions; |
261 if (previous_transmissions == NULL) { | 257 if (previous_transmissions == NULL) { |
| 258 if (it->second.retransmittable_frames == NULL) { |
| 259 // This is a current transmission, but a previous transmission has |
| 260 // been acked, so it's safe to remove. |
| 261 it = MarkPacketHandled(sequence_number, NOT_RECEIVED_BY_PEER); |
| 262 --num_to_clear; |
| 263 continue; |
| 264 } |
262 break; | 265 break; |
263 } | 266 } |
264 QuicPacketSequenceNumber newest_transmission = | 267 QuicPacketSequenceNumber newest_transmission = |
265 *previous_transmissions->rbegin(); | 268 *previous_transmissions->rbegin(); |
266 if (sequence_number == newest_transmission) { | 269 if (sequence_number == newest_transmission) { |
267 break; | 270 break; |
268 } | 271 } |
269 | 272 |
270 DCHECK(it->second.retransmittable_frames == NULL); | 273 DCHECK(it->second.retransmittable_frames == NULL); |
271 previous_transmissions->erase(sequence_number); | 274 previous_transmissions->erase(sequence_number); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 unacked_packets_.find(newest_transmission); | 418 unacked_packets_.find(newest_transmission); |
416 if (HasCryptoHandshake(newest_it->second)) { | 419 if (HasCryptoHandshake(newest_it->second)) { |
417 --pending_crypto_packet_count_; | 420 --pending_crypto_packet_count_; |
418 } | 421 } |
419 // If we have received an ack for a previous transmission of a packet, | 422 // If we have received an ack for a previous transmission of a packet, |
420 // we want to keep the "new" transmission of the packet unacked, | 423 // we want to keep the "new" transmission of the packet unacked, |
421 // but prevent the data from being retransmitted. | 424 // but prevent the data from being retransmitted. |
422 delete newest_it->second.retransmittable_frames; | 425 delete newest_it->second.retransmittable_frames; |
423 newest_it->second.retransmittable_frames = NULL; | 426 newest_it->second.retransmittable_frames = NULL; |
424 newest_it->second.previous_transmissions = NULL; | 427 newest_it->second.previous_transmissions = NULL; |
425 pending_retransmissions_.erase(newest_transmission); | |
426 } | 428 } |
427 | 429 |
428 // Clear out information all previous transmissions. | 430 // Clear out information all previous transmissions. |
429 ++previous_transmissions_it; | 431 ++previous_transmissions_it; |
430 while (previous_transmissions_it != previous_transmissions->rend()) { | 432 while (previous_transmissions_it != previous_transmissions->rend()) { |
431 QuicPacketSequenceNumber previous_transmission = *previous_transmissions_it; | 433 QuicPacketSequenceNumber previous_transmission = *previous_transmissions_it; |
432 ++previous_transmissions_it; | 434 ++previous_transmissions_it; |
433 // If the packet was TLP retransmitted, the old copy was not yet considered | 435 // If the packet was TLP retransmitted, the old copy was not yet considered |
434 // lost or abandoned, so do that now. | 436 // lost or abandoned, so do that now. |
435 if (ContainsKey(pending_packets_, previous_transmission)) { | 437 if (ContainsKey(pending_packets_, previous_transmission)) { |
436 send_algorithm_->OnPacketLost(previous_transmission, clock_->Now()); | 438 send_algorithm_->OnPacketLost(previous_transmission, clock_->Now()); |
437 OnPacketAbandoned(previous_transmission); | 439 OnPacketAbandoned(previous_transmission); |
438 } | 440 } |
439 DiscardPacket(previous_transmission); | 441 DiscardPacket(previous_transmission); |
440 } | 442 } |
441 | 443 |
442 delete previous_transmissions; | 444 delete previous_transmissions; |
443 | 445 |
| 446 if (ContainsKey(pending_retransmissions_, newest_transmission)) { |
| 447 pending_retransmissions_.erase(newest_transmission); |
| 448 if (!ContainsKey(pending_packets_, newest_transmission)) { |
| 449 // If the newest transmission has already been marked for retransmission |
| 450 // and has already been abandoned, then we should remove it from |
| 451 // unacked_packets_, as well as cancel the retransmission. |
| 452 DCHECK(ContainsKey(unacked_packets_, newest_transmission)); |
| 453 DCHECK(!unacked_packets_[newest_transmission].previous_transmissions); |
| 454 unacked_packets_.erase(newest_transmission); |
| 455 } |
| 456 } |
| 457 |
444 UnackedPacketMap::iterator next_unacked = unacked_packets_.begin(); | 458 UnackedPacketMap::iterator next_unacked = unacked_packets_.begin(); |
445 while (next_unacked != unacked_packets_.end() && | 459 while (next_unacked != unacked_packets_.end() && |
446 next_unacked->first < sequence_number) { | 460 next_unacked->first < sequence_number) { |
447 ++next_unacked; | 461 ++next_unacked; |
448 } | 462 } |
449 return next_unacked; | 463 return next_unacked; |
450 } | 464 } |
451 | 465 |
452 void QuicSentPacketManager::DiscardPacket( | 466 void QuicSentPacketManager::DiscardPacket( |
453 QuicPacketSequenceNumber sequence_number) { | 467 QuicPacketSequenceNumber sequence_number) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 MarkForRetransmission(sequence_number, TLP_RETRANSMISSION); | 633 MarkForRetransmission(sequence_number, TLP_RETRANSMISSION); |
620 return; | 634 return; |
621 } | 635 } |
622 DLOG(FATAL) | 636 DLOG(FATAL) |
623 << "No retransmittable packets, so RetransmitOldestPacket failed."; | 637 << "No retransmittable packets, so RetransmitOldestPacket failed."; |
624 } | 638 } |
625 | 639 |
626 void QuicSentPacketManager::RetransmitAllPackets() { | 640 void QuicSentPacketManager::RetransmitAllPackets() { |
627 // Abandon all retransmittable packets and packets older than the | 641 // Abandon all retransmittable packets and packets older than the |
628 // retransmission delay. | 642 // retransmission delay. |
629 QuicTime::Delta retransmission_delay = GetRetransmissionDelay(); | |
630 QuicTime max_send_time = | |
631 clock_->ApproximateNow().Subtract(retransmission_delay); | |
632 | 643 |
633 DVLOG(1) << "OnRetransmissionTimeout() fired with " | 644 DVLOG(1) << "OnRetransmissionTimeout() fired with " |
634 << unacked_packets_.size() << " unacked packets."; | 645 << unacked_packets_.size() << " unacked packets."; |
635 | 646 |
636 // Request retransmission of all retransmittable packets when the RTO | 647 // Request retransmission of all retransmittable packets when the RTO |
637 // fires, and let the congestion manager decide how many to send | 648 // fires, and let the congestion manager decide how many to send |
638 // immediately and the remaining packets will be queued. | 649 // immediately and the remaining packets will be queued. |
639 // Abandon any non-retransmittable packets that are sufficiently old. | 650 // Abandon any non-retransmittable packets that are sufficiently old. |
640 bool packets_retransmitted = false; | 651 bool packets_retransmitted = false; |
641 for (UnackedPacketMap::const_iterator it = unacked_packets_.begin(); | 652 for (UnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
642 it != unacked_packets_.end(); ++it) { | 653 it != unacked_packets_.end(); ++it) { |
643 if (it->second.retransmittable_frames != NULL) { | 654 if (it->second.retransmittable_frames != NULL) { |
644 OnPacketAbandoned(it->first); | |
645 packets_retransmitted = true; | 655 packets_retransmitted = true; |
646 MarkForRetransmission(it->first, RTO_RETRANSMISSION); | 656 MarkForRetransmission(it->first, RTO_RETRANSMISSION); |
647 } else if (it->second.sent_time <= max_send_time) { | |
648 OnPacketAbandoned(it->first); | |
649 } | 657 } |
650 } | 658 } |
651 | 659 |
652 // Only inform the send algorithm of an RTO if data was retransmitted. | 660 pending_packets_.clear(); |
| 661 send_algorithm_->OnRetransmissionTimeout(packets_retransmitted); |
653 if (packets_retransmitted) { | 662 if (packets_retransmitted) { |
654 ++consecutive_rto_count_; | 663 ++consecutive_rto_count_; |
655 send_algorithm_->OnRetransmissionTimeout(); | |
656 } | 664 } |
657 } | 665 } |
658 | 666 |
659 QuicSentPacketManager::RetransmissionTimeoutMode | 667 QuicSentPacketManager::RetransmissionTimeoutMode |
660 QuicSentPacketManager::GetRetransmissionMode() const { | 668 QuicSentPacketManager::GetRetransmissionMode() const { |
661 DCHECK(!pending_packets_.empty()); | 669 DCHECK(!pending_packets_.empty()); |
662 if (pending_crypto_packet_count_ > 0) { | 670 if (pending_crypto_packet_count_ > 0) { |
663 return HANDSHAKE_MODE; | 671 return HANDSHAKE_MODE; |
664 } | 672 } |
665 if (consecutive_tlp_count_ < max_tail_loss_probes_) { | 673 if (consecutive_tlp_count_ < max_tail_loss_probes_) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 // If the number of retransmissions has maxed out, don't lose or retransmit | 751 // If the number of retransmissions has maxed out, don't lose or retransmit |
744 // any more packets. | 752 // any more packets. |
745 if (num_retransmitted >= kMaxRetransmissionsPerAck) { | 753 if (num_retransmitted >= kMaxRetransmissionsPerAck) { |
746 ++it; | 754 ++it; |
747 continue; | 755 continue; |
748 } | 756 } |
749 | 757 |
750 lost_packets.insert(sequence_number); | 758 lost_packets.insert(sequence_number); |
751 if (transmission_info.retransmittable_frames) { | 759 if (transmission_info.retransmittable_frames) { |
752 ++num_retransmitted; | 760 ++num_retransmitted; |
753 MarkForRetransmission(*it, NACK_RETRANSMISSION); | 761 MarkForRetransmission(sequence_number, NACK_RETRANSMISSION); |
| 762 } else { |
| 763 // Since we will not retransmit this, we need to remove it from |
| 764 // unacked_packets_. This is either the current transmission of |
| 765 // a packet whose previous transmission has been acked, or it |
| 766 // is a packet that has been TLP retransmitted. |
| 767 RemovePreviousTransmission(sequence_number); |
| 768 unacked_packets_.erase(sequence_number); |
754 } | 769 } |
755 | 770 |
756 ++it; | 771 ++it; |
757 } | 772 } |
758 // Abandon packets after the loop over pending packets, because otherwise it | 773 // Abandon packets after the loop over pending packets, because otherwise it |
759 // changes the early retransmit logic and iteration. | 774 // changes the early retransmit logic and iteration. |
760 for (SequenceNumberSet::const_iterator it = lost_packets.begin(); | 775 for (SequenceNumberSet::const_iterator it = lost_packets.begin(); |
761 it != lost_packets.end(); ++it) { | 776 it != lost_packets.end(); ++it) { |
762 // TODO(ianswett): OnPacketLost is also called from TCPCubicSender when | 777 // TODO(ianswett): OnPacketLost is also called from TCPCubicSender when |
763 // an FEC packet is lost, but FEC loss information should be shared among | 778 // an FEC packet is lost, but FEC loss information should be shared among |
764 // congestion managers. Additionally, if it's expected the FEC packet may | 779 // congestion managers. Additionally, if it's expected the FEC packet may |
765 // repair the loss, it should be recorded as a loss to the congestion | 780 // repair the loss, it should be recorded as a loss to the congestion |
766 // manager, but not retransmitted until it's known whether the FEC packet | 781 // manager, but not retransmitted until it's known whether the FEC packet |
767 // arrived. | 782 // arrived. |
768 send_algorithm_->OnPacketLost(*it, ack_receive_time); | 783 QuicPacketSequenceNumber lost_packet = *it; |
769 OnPacketAbandoned(*it); | 784 send_algorithm_->OnPacketLost(lost_packet, ack_receive_time); |
| 785 OnPacketAbandoned(lost_packet); |
770 } | 786 } |
771 } | 787 } |
772 | 788 |
773 void QuicSentPacketManager::MaybeUpdateRTT( | 789 void QuicSentPacketManager::MaybeUpdateRTT( |
774 const ReceivedPacketInfo& received_info, | 790 const ReceivedPacketInfo& received_info, |
775 const QuicTime& ack_receive_time) { | 791 const QuicTime& ack_receive_time) { |
776 // We calculate the RTT based on the highest ACKed sequence number, the lower | 792 // We calculate the RTT based on the highest ACKed sequence number, the lower |
777 // sequence numbers will include the ACK aggregation delay. | 793 // sequence numbers will include the ACK aggregation delay. |
778 SendAlgorithmInterface::SentPacketsMap::iterator history_it = | 794 SendAlgorithmInterface::SentPacketsMap::iterator history_it = |
779 packet_history_map_.find(received_info.largest_observed); | 795 packet_history_map_.find(received_info.largest_observed); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 QuicTime rto_timeout = sent_time.Add(GetRetransmissionDelay()); | 866 QuicTime rto_timeout = sent_time.Add(GetRetransmissionDelay()); |
851 | 867 |
852 return QuicTime::Max(min_timeout, rto_timeout); | 868 return QuicTime::Max(min_timeout, rto_timeout); |
853 } | 869 } |
854 default: | 870 default: |
855 DCHECK(false); | 871 DCHECK(false); |
856 } | 872 } |
857 return QuicTime::Zero(); | 873 return QuicTime::Zero(); |
858 } | 874 } |
859 | 875 |
860 const QuicTime::Delta | 876 const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay() |
861 QuicSentPacketManager::GetCryptoRetransmissionDelay() const { | 877 const { |
862 // This is equivalent to the TailLossProbeDelay, but slightly more aggressive | 878 // This is equivalent to the TailLossProbeDelay, but slightly more aggressive |
863 // because crypto handshake messages don't incur a delayed ack time. | 879 // because crypto handshake messages don't incur a delayed ack time. |
864 int64 delay_ms = max<int64>(kMinHandshakeTimeoutMs, | 880 int64 delay_ms = max<int64>(kMinHandshakeTimeoutMs, |
865 1.5 * SmoothedRtt().ToMilliseconds()); | 881 1.5 * SmoothedRtt().ToMilliseconds()); |
866 return QuicTime::Delta::FromMilliseconds( | 882 return QuicTime::Delta::FromMilliseconds( |
867 delay_ms << consecutive_crypto_retransmission_count_); | 883 delay_ms << consecutive_crypto_retransmission_count_); |
868 } | 884 } |
869 | 885 |
870 const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const { | 886 const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const { |
871 QuicTime::Delta srtt = SmoothedRtt(); | 887 QuicTime::Delta srtt = SmoothedRtt(); |
872 if (pending_packets_.size() == 1) { | 888 if (pending_packets_.size() == 1) { |
873 return QuicTime::Delta::Max( | 889 return QuicTime::Delta::Max( |
874 srtt.Multiply(1.5).Add(DelayedAckTime()), srtt.Multiply(2)); | 890 srtt.Multiply(1.5).Add(DelayedAckTime()), srtt.Multiply(2)); |
875 } | 891 } |
876 return QuicTime::Delta::FromMilliseconds( | 892 return QuicTime::Delta::FromMilliseconds( |
877 max(kMinTailLossProbeTimeoutMs, | 893 max(kMinTailLossProbeTimeoutMs, |
878 static_cast<int64>(2 * srtt.ToMilliseconds()))); | 894 static_cast<int64>(2 * srtt.ToMilliseconds()))); |
879 } | 895 } |
880 | 896 |
881 const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const { | 897 const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const { |
882 size_t number_retransmissions = consecutive_rto_count_; | |
883 // TODO(ianswett): Remove this flag now that EndToEndTest is no longer flaky. | |
884 if (FLAGS_limit_rto_increase_for_tests) { | |
885 const size_t kTailDropWindowSize = 5; | |
886 const size_t kTailDropMaxRetransmissions = 4; | |
887 if (pending_packets_.size() <= kTailDropWindowSize) { | |
888 // Avoid exponential backoff of RTO when there are only a few packets | |
889 // outstanding. This helps avoid the situation where fake packet loss | |
890 // causes a packet and it's retransmission to be dropped causing | |
891 // test timouts. | |
892 if (number_retransmissions <= kTailDropMaxRetransmissions) { | |
893 number_retransmissions = 0; | |
894 } else { | |
895 number_retransmissions -= kTailDropMaxRetransmissions; | |
896 } | |
897 } | |
898 } | |
899 | |
900 QuicTime::Delta retransmission_delay = send_algorithm_->RetransmissionDelay(); | 898 QuicTime::Delta retransmission_delay = send_algorithm_->RetransmissionDelay(); |
901 if (retransmission_delay.IsZero()) { | 899 if (retransmission_delay.IsZero()) { |
902 // We are in the initial state, use default timeout values. | 900 // We are in the initial state, use default timeout values. |
903 retransmission_delay = | 901 retransmission_delay = |
904 QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs); | 902 QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs); |
905 } | 903 } |
906 // Calculate exponential back off. | 904 // Calculate exponential back off. |
907 retransmission_delay = retransmission_delay.Multiply( | 905 retransmission_delay = retransmission_delay.Multiply( |
908 1 << min<size_t>(number_retransmissions, kMaxRetransmissions)); | 906 1 << min<size_t>(consecutive_rto_count_, kMaxRetransmissions)); |
909 | 907 |
910 // TODO(rch): This code should move to |send_algorithm_|. | 908 // TODO(rch): This code should move to |send_algorithm_|. |
911 if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) { | 909 if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) { |
912 return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs); | 910 return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs); |
913 } | 911 } |
914 if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) { | 912 if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) { |
915 return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs); | 913 return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs); |
916 } | 914 } |
917 return retransmission_delay; | 915 return retransmission_delay; |
918 } | 916 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 if (using_pacing_) { | 956 if (using_pacing_) { |
959 return; | 957 return; |
960 } | 958 } |
961 | 959 |
962 using_pacing_ = true; | 960 using_pacing_ = true; |
963 send_algorithm_.reset( | 961 send_algorithm_.reset( |
964 new PacingSender(send_algorithm_.release(), | 962 new PacingSender(send_algorithm_.release(), |
965 QuicTime::Delta::FromMicroseconds(1))); | 963 QuicTime::Delta::FromMicroseconds(1))); |
966 } | 964 } |
967 | 965 |
| 966 void QuicSentPacketManager::RemovePreviousTransmission( |
| 967 QuicPacketSequenceNumber sequence_number) { |
| 968 SequenceNumberSet* previous_transmissions = |
| 969 unacked_packets_[sequence_number].previous_transmissions; |
| 970 if (!previous_transmissions) { |
| 971 return; |
| 972 } |
| 973 previous_transmissions->erase(sequence_number); |
| 974 if (previous_transmissions->size() == 1) { |
| 975 QuicPacketSequenceNumber current = *previous_transmissions->begin(); |
| 976 unacked_packets_[current].previous_transmissions = NULL; |
| 977 delete previous_transmissions; |
| 978 } |
| 979 } |
| 980 |
968 } // namespace net | 981 } // namespace net |
OLD | NEW |