blob: 61d30f78dd166c36045dbde362d7d63d0e02360d [file] [log] [blame] [edit]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "quiche/quic/core/quic_coalesced_packet.h"
#include <string>
#include "quiche/quic/platform/api/quic_expect_bug.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
#include "quiche/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
namespace {
TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
QuicCoalescedPacket coalesced;
EXPECT_EQ("total_length: 0 padding_size: 0 packets: {}",
coalesced.ToString(0));
quiche::SimpleBufferAllocator allocator;
EXPECT_EQ(0u, coalesced.length());
EXPECT_EQ(0u, coalesced.NumberOfPackets());
char buffer[1000];
QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
SerializedPacket packet1(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet1.transmission_type = PTO_RETRANSMISSION;
QuicAckFrame ack_frame(InitAckFrame(1));
packet1.nonretransmittable_frames.push_back(QuicFrame(&ack_frame));
packet1.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, true, 0, 100)));
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(PTO_RETRANSMISSION,
coalesced.TransmissionTypeOfPacket(ENCRYPTION_INITIAL));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(500u, coalesced.length());
EXPECT_EQ(1u, coalesced.NumberOfPackets());
EXPECT_EQ(
"total_length: 1500 padding_size: 1000 packets: {ENCRYPTION_INITIAL}",
coalesced.ToString(1500));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
// Cannot coalesce packet of the same encryption level.
SerializedPacket packet2(QuicPacketNumber(2), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
EXPECT_FALSE(coalesced.MaybeCoalescePacket(
packet2, self_address, peer_address, &allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
SerializedPacket packet3(QuicPacketNumber(3), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet3.nonretransmittable_frames.push_back(QuicFrame(QuicPaddingFrame(100)));
packet3.encryption_level = ENCRYPTION_ZERO_RTT;
packet3.transmission_type = LOSS_RETRANSMISSION;
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet3, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
EXPECT_EQ(2u, coalesced.NumberOfPackets());
EXPECT_EQ(LOSS_RETRANSMISSION,
coalesced.TransmissionTypeOfPacket(ENCRYPTION_ZERO_RTT));
EXPECT_EQ(
"total_length: 1500 padding_size: 500 packets: {ENCRYPTION_INITIAL, "
"ENCRYPTION_ZERO_RTT}",
coalesced.ToString(1500));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
SerializedPacket packet4(QuicPacketNumber(4), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet4.encryption_level = ENCRYPTION_FORWARD_SECURE;
// Cannot coalesce packet of changed self/peer address.
EXPECT_FALSE(coalesced.MaybeCoalescePacket(
packet4, QuicSocketAddress(QuicIpAddress::Loopback4(), 3), peer_address,
&allocator, 1500, ECN_NOT_ECT));
// Packet does not fit.
SerializedPacket packet5(QuicPacketNumber(5), PACKET_4BYTE_PACKET_NUMBER,
buffer, 501, false, false);
packet5.encryption_level = ENCRYPTION_FORWARD_SECURE;
EXPECT_FALSE(coalesced.MaybeCoalescePacket(
packet5, self_address, peer_address, &allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
EXPECT_EQ(2u, coalesced.NumberOfPackets());
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
// Max packet number length changed.
SerializedPacket packet6(QuicPacketNumber(6), PACKET_4BYTE_PACKET_NUMBER,
buffer, 100, false, false);
packet6.encryption_level = ENCRYPTION_FORWARD_SECURE;
EXPECT_QUIC_BUG(
coalesced.MaybeCoalescePacket(packet6, self_address, peer_address,
&allocator, 1000, ECN_NOT_ECT),
"Max packet length changes in the middle of the write path");
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
EXPECT_EQ(2u, coalesced.NumberOfPackets());
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
}
TEST(QuicCoalescedPacketTest, CopyEncryptedBuffers) {
QuicCoalescedPacket coalesced;
quiche::SimpleBufferAllocator allocator;
QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
std::string buffer(500, 'a');
std::string buffer2(500, 'b');
SerializedPacket packet1(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
buffer.data(), 500,
/*has_ack=*/false, /*has_stop_waiting=*/false);
packet1.encryption_level = ENCRYPTION_ZERO_RTT;
SerializedPacket packet2(QuicPacketNumber(2), PACKET_4BYTE_PACKET_NUMBER,
buffer2.data(), 500,
/*has_ack=*/false, /*has_stop_waiting=*/false);
packet2.encryption_level = ENCRYPTION_FORWARD_SECURE;
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet2, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(1000u, coalesced.length());
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
char copy_buffer[1000];
size_t length_copied = 0;
EXPECT_FALSE(
coalesced.CopyEncryptedBuffers(copy_buffer, 900, &length_copied));
ASSERT_TRUE(
coalesced.CopyEncryptedBuffers(copy_buffer, 1000, &length_copied));
EXPECT_EQ(1000u, length_copied);
char expected[1000];
memset(expected, 'a', 500);
memset(expected + 500, 'b', 500);
quiche::test::CompareCharArraysWithHexError("copied buffers", copy_buffer,
length_copied, expected, 1000);
}
TEST(QuicCoalescedPacketTest, NeuterInitialPacket) {
QuicCoalescedPacket coalesced;
EXPECT_EQ("total_length: 0 padding_size: 0 packets: {}",
coalesced.ToString(0));
// Noop when neutering initial packet on a empty coalescer.
coalesced.NeuterInitialPacket();
EXPECT_EQ("total_length: 0 padding_size: 0 packets: {}",
coalesced.ToString(0));
quiche::SimpleBufferAllocator allocator;
EXPECT_EQ(0u, coalesced.length());
char buffer[1000];
QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
SerializedPacket packet1(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet1.transmission_type = PTO_RETRANSMISSION;
QuicAckFrame ack_frame(InitAckFrame(1));
packet1.nonretransmittable_frames.push_back(QuicFrame(&ack_frame));
packet1.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, true, 0, 100)));
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(PTO_RETRANSMISSION,
coalesced.TransmissionTypeOfPacket(ENCRYPTION_INITIAL));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(500u, coalesced.length());
EXPECT_EQ(
"total_length: 1500 padding_size: 1000 packets: {ENCRYPTION_INITIAL}",
coalesced.ToString(1500));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
coalesced.NeuterInitialPacket();
EXPECT_EQ(0u, coalesced.max_packet_length());
EXPECT_EQ(0u, coalesced.length());
EXPECT_EQ("total_length: 0 padding_size: 0 packets: {}",
coalesced.ToString(0));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
// Coalesce initial packet again.
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
SerializedPacket packet2(QuicPacketNumber(3), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet2.nonretransmittable_frames.push_back(QuicFrame(QuicPaddingFrame(100)));
packet2.encryption_level = ENCRYPTION_ZERO_RTT;
packet2.transmission_type = LOSS_RETRANSMISSION;
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet2, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
EXPECT_EQ(LOSS_RETRANSMISSION,
coalesced.TransmissionTypeOfPacket(ENCRYPTION_ZERO_RTT));
EXPECT_EQ(
"total_length: 1500 padding_size: 500 packets: {ENCRYPTION_INITIAL, "
"ENCRYPTION_ZERO_RTT}",
coalesced.ToString(1500));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
// Neuter initial packet.
coalesced.NeuterInitialPacket();
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(500u, coalesced.length());
EXPECT_EQ(
"total_length: 1500 padding_size: 1000 packets: {ENCRYPTION_ZERO_RTT}",
coalesced.ToString(1500));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
SerializedPacket packet3(QuicPacketNumber(5), PACKET_4BYTE_PACKET_NUMBER,
buffer, 501, false, false);
packet3.encryption_level = ENCRYPTION_FORWARD_SECURE;
EXPECT_TRUE(coalesced.MaybeCoalescePacket(packet3, self_address, peer_address,
&allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1001u, coalesced.length());
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
// Neuter initial packet.
coalesced.NeuterInitialPacket();
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1001u, coalesced.length());
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_NOT_ECT);
}
TEST(QuicCoalescedPacketTest, DoNotCoalesceDifferentEcn) {
QuicCoalescedPacket coalesced;
EXPECT_EQ("total_length: 0 padding_size: 0 packets: {}",
coalesced.ToString(0));
quiche::SimpleBufferAllocator allocator;
EXPECT_EQ(0u, coalesced.length());
EXPECT_EQ(0u, coalesced.NumberOfPackets());
char buffer[1000];
QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
SerializedPacket packet1(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet1.transmission_type = PTO_RETRANSMISSION;
QuicAckFrame ack_frame(InitAckFrame(1));
packet1.nonretransmittable_frames.push_back(QuicFrame(&ack_frame));
packet1.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, true, 0, 100)));
ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
&allocator, 1500, ECN_ECT1));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_ECT1);
SerializedPacket packet2(QuicPacketNumber(2), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
packet2.nonretransmittable_frames.push_back(QuicFrame(QuicPaddingFrame(100)));
packet2.encryption_level = ENCRYPTION_ZERO_RTT;
packet2.transmission_type = LOSS_RETRANSMISSION;
EXPECT_FALSE(coalesced.MaybeCoalescePacket(
packet2, self_address, peer_address, &allocator, 1500, ECN_NOT_ECT));
EXPECT_EQ(coalesced.ecn_codepoint(), ECN_ECT1);
}
} // namespace
} // namespace test
} // namespace quic