Add QoS dimension to packet processor result metrics. PiperOrigin-RevId: 617205961
diff --git a/quiche/quic/qbone/qbone_packet_processor.cc b/quiche/quic/qbone/qbone_packet_processor.cc index 75cf6d1..7fdfd0f 100644 --- a/quiche/quic/qbone/qbone_packet_processor.cc +++ b/quiche/quic/qbone/qbone_packet_processor.cc
@@ -8,6 +8,7 @@ #include <netinet/in.h> #include <netinet/ip6.h> +#include <cstdint> #include <cstring> #include "absl/base/optimization.h" @@ -68,10 +69,11 @@ void QbonePacketProcessor::ProcessPacket(std::string* packet, Direction direction) { + uint8_t traffic_class = TrafficClassFromHeader(*packet); if (ABSL_PREDICT_FALSE(!IsValid())) { QUIC_BUG(quic_bug_11024_1) << "QuicPacketProcessor is invoked in an invalid state."; - stats_->OnPacketDroppedSilently(direction); + stats_->OnPacketDroppedSilently(direction, traffic_class); return; } @@ -96,13 +98,13 @@ output_->SendPacketToClient(*packet); break; } - stats_->OnPacketForwarded(direction); + stats_->OnPacketForwarded(direction, traffic_class); break; case ProcessingResult::SILENT_DROP: - stats_->OnPacketDroppedSilently(direction); + stats_->OnPacketDroppedSilently(direction, traffic_class); break; case ProcessingResult::DEFER: - stats_->OnPacketDeferred(direction); + stats_->OnPacketDeferred(direction, traffic_class); break; case ProcessingResult::ICMP: if (icmp_header.icmp6_type == ICMP6_ECHO_REPLY) { @@ -115,17 +117,17 @@ } else { SendIcmpResponse(dst, &icmp_header, *packet, direction); } - stats_->OnPacketDroppedWithIcmp(direction); + stats_->OnPacketDroppedWithIcmp(direction, traffic_class); break; case ProcessingResult::ICMP_AND_TCP_RESET: SendIcmpResponse(dst, &icmp_header, *packet, direction); - stats_->OnPacketDroppedWithIcmp(direction); + stats_->OnPacketDroppedWithIcmp(direction, traffic_class); SendTcpReset(*packet, direction); - stats_->OnPacketDroppedWithTcpReset(direction); + stats_->OnPacketDroppedWithTcpReset(direction, traffic_class); break; case ProcessingResult::TCP_RESET: SendTcpReset(*packet, direction); - stats_->OnPacketDroppedWithTcpReset(direction); + stats_->OnPacketDroppedWithTcpReset(direction, traffic_class); break; } } @@ -288,4 +290,15 @@ } } +uint8_t QbonePacketProcessor::TrafficClassFromHeader( + absl::string_view ipv6_header) { + // Packets that reach this function should have already been validated. + // However, there are tests that bypass that validation that fail because this + // would be out of bounds. + if (ipv6_header.length() < 2) { + return 0; // Default to BE1 + } + + return ipv6_header[0] << 4 | ipv6_header[1] >> 4; +} } // namespace quic
diff --git a/quiche/quic/qbone/qbone_packet_processor.h b/quiche/quic/qbone/qbone_packet_processor.h index fed7a8b..b337b19 100644 --- a/quiche/quic/qbone/qbone_packet_processor.h +++ b/quiche/quic/qbone/qbone_packet_processor.h
@@ -9,6 +9,8 @@ #include <netinet/in.h> #include <netinet/ip6.h> +#include <cstdint> + #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_ip_address.h" @@ -63,11 +65,16 @@ public: virtual ~StatsInterface(); - virtual void OnPacketForwarded(Direction direction) = 0; - virtual void OnPacketDroppedSilently(Direction direction) = 0; - virtual void OnPacketDroppedWithIcmp(Direction direction) = 0; - virtual void OnPacketDroppedWithTcpReset(Direction direction) = 0; - virtual void OnPacketDeferred(Direction direction) = 0; + virtual void OnPacketForwarded(Direction direction, + uint8_t traffic_class) = 0; + virtual void OnPacketDroppedSilently(Direction direction, + uint8_t traffic_class) = 0; + virtual void OnPacketDroppedWithIcmp(Direction direction, + uint8_t traffic_class) = 0; + virtual void OnPacketDroppedWithTcpReset(Direction direction, + uint8_t traffic_class) = 0; + virtual void OnPacketDeferred(Direction direction, + uint8_t traffic_class) = 0; }; // Allows to implement a custom packet filter on top of the filtering done by @@ -110,9 +117,6 @@ uint8_t TransportProtocolFromHeader(absl::string_view ipv6_header) { return ipv6_header[6]; } - uint8_t TrafficClassFromHeader(absl::string_view ipv6_header) { - return ipv6_header[0] << 4 | ipv6_header[1] >> 4; - } QuicIpAddress SourceIpFromHeader(absl::string_view ipv6_header) { QuicIpAddress address; @@ -158,6 +162,9 @@ static const QuicIpAddress kInvalidIpAddress; + // This function assumes that the packet is valid. + static uint8_t TrafficClassFromHeader(absl::string_view ipv6_header); + protected: // Processes the header and returns what should be done with the packet. // After that, calls an external packet filter if registered. TTL of the
diff --git a/quiche/quic/qbone/qbone_packet_processor_test.cc b/quiche/quic/qbone/qbone_packet_processor_test.cc index 85cf0ca..f3361b7 100644 --- a/quiche/quic/qbone/qbone_packet_processor_test.cc +++ b/quiche/quic/qbone/qbone_packet_processor_test.cc
@@ -355,18 +355,18 @@ }; TEST_F(QbonePacketProcessorTest, EmptyPacket) { - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _)); SendPacketFromClient(""); - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK, _)); SendPacketFromNetwork(""); } TEST_F(QbonePacketProcessorTest, RandomGarbage) { - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _)); SendPacketFromClient(std::string(1280, 'a')); - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK, _)); SendPacketFromNetwork(std::string(1280, 'a')); } @@ -375,31 +375,31 @@ packet[4] = 0; packet[5] = 0; - EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK, _)); EXPECT_CALL(output_, SendPacketToClient(IsIcmpMessage(ICMP6_DST_UNREACH))); SendPacketFromClient(packet); } TEST_F(QbonePacketProcessorTest, GoodPacketFromClient) { - EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK, _)); EXPECT_CALL(output_, SendPacketToNetwork(_)); SendPacketFromClient(kReferenceClientPacket); } TEST_F(QbonePacketProcessorTest, GoodPacketFromClientSubnet) { - EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK, _)); EXPECT_CALL(output_, SendPacketToNetwork(_)); SendPacketFromClient(kReferenceClientSubnetPacket); } TEST_F(QbonePacketProcessorTest, GoodPacketFromNetwork) { - EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_NETWORK)); + EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_NETWORK, _)); EXPECT_CALL(output_, SendPacketToClient(_)); SendPacketFromNetwork(kReferenceNetworkPacket); } TEST_F(QbonePacketProcessorTest, GoodPacketFromNetworkWrongDirection) { - EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK, _)); EXPECT_CALL(output_, SendPacketToClient(IsIcmpMessage(ICMP6_DST_UNREACH))); SendPacketFromClient(kReferenceNetworkPacket); } @@ -408,7 +408,7 @@ std::string packet(kReferenceNetworkPacket); packet[7] = 1; - EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK, _)); EXPECT_CALL(output_, SendPacketToNetwork(IsIcmpMessage(ICMP6_TIME_EXCEEDED))); SendPacketFromNetwork(packet); } @@ -417,7 +417,7 @@ std::string packet(kReferenceNetworkPacket); packet[6] = IPPROTO_SCTP; - EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK, _)); EXPECT_CALL(output_, SendPacketToNetwork(IsIcmpMessage(ICMP6_PARAM_PROB))); SendPacketFromNetwork(packet); } @@ -428,7 +428,7 @@ .WillRepeatedly(Return(ProcessingResult::SILENT_DROP)); processor_->set_filter(std::move(filter)); - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _)); SendPacketFromClient(kReferenceClientPacket); } @@ -446,7 +446,7 @@ EXPECT_EQ(client_ip_, SourceIpFromHeader(full_packet)); EXPECT_EQ(network_ip_, DestinationIpFromHeader(full_packet)); - last_tos_ = TrafficClassFromHeader(full_packet); + last_tos_ = QbonePacketProcessor::TrafficClassFromHeader(full_packet); called_++; return ProcessingResult::SILENT_DROP; } @@ -469,7 +469,7 @@ TestFilter* filter = filter_owned.get(); processor_->set_filter(std::move(filter_owned)); - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _)); SendPacketFromClient(kReferenceClientPacket); ASSERT_EQ(1, filter->called()); } @@ -479,7 +479,7 @@ TestFilter* filter = filter_owned.get(); processor_->set_filter(std::move(filter_owned)); - EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK)) + EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _)) .Times(testing::AnyNumber()); SendPacketFromClient(kReferenceClientPacket); ASSERT_EQ(0, filter->last_tos()); @@ -508,7 +508,7 @@ }))); processor_->set_filter(std::move(filter)); - EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK)); + EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK, _)); EXPECT_CALL(output_, SendPacketToClient(_)) .WillOnce(Invoke([](absl::string_view packet) { // Explicit conversion because otherwise it is treated as a null
diff --git a/quiche/quic/qbone/qbone_packet_processor_test_tools.h b/quiche/quic/qbone/qbone_packet_processor_test_tools.h index 3d3492d..9b0ff85 100644 --- a/quiche/quic/qbone/qbone_packet_processor_test_tools.h +++ b/quiche/quic/qbone/qbone_packet_processor_test_tools.h
@@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_QBONE_QBONE_PACKET_PROCESSOR_TEST_TOOLS_H_ #define QUICHE_QUIC_QBONE_QBONE_PACKET_PROCESSOR_TEST_TOOLS_H_ +#include <cstdint> + #include "absl/strings/string_view.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/qbone/qbone_packet_processor.h" @@ -23,16 +25,16 @@ public: MockPacketProcessorStats() {} - MOCK_METHOD(void, OnPacketForwarded, (QbonePacketProcessor::Direction), - (override)); - MOCK_METHOD(void, OnPacketDroppedSilently, (QbonePacketProcessor::Direction), - (override)); - MOCK_METHOD(void, OnPacketDroppedWithIcmp, (QbonePacketProcessor::Direction), - (override)); + MOCK_METHOD(void, OnPacketForwarded, + (QbonePacketProcessor::Direction, uint8_t), (override)); + MOCK_METHOD(void, OnPacketDroppedSilently, + (QbonePacketProcessor::Direction, uint8_t), (override)); + MOCK_METHOD(void, OnPacketDroppedWithIcmp, + (QbonePacketProcessor::Direction, uint8_t), (override)); MOCK_METHOD(void, OnPacketDroppedWithTcpReset, - (QbonePacketProcessor::Direction), (override)); - MOCK_METHOD(void, OnPacketDeferred, (QbonePacketProcessor::Direction), - (override)); + (QbonePacketProcessor::Direction, uint8_t), (override)); + MOCK_METHOD(void, OnPacketDeferred, + (QbonePacketProcessor::Direction, uint8_t), (override)); }; std::string PrependIPv6HeaderForTest(const std::string& body, int hops);
diff --git a/quiche/quic/qbone/qbone_server_session.h b/quiche/quic/qbone/qbone_server_session.h index c313816..0f325a6 100644 --- a/quiche/quic/qbone/qbone_server_session.h +++ b/quiche/quic/qbone/qbone_server_session.h
@@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_QBONE_QBONE_SERVER_SESSION_H_ #define QUICHE_QUIC_QBONE_QBONE_SERVER_SESSION_H_ +#include <cstdint> + #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_crypto_server_stream_base.h" #include "quiche/quic/core/quic_crypto_stream.h" @@ -59,14 +61,16 @@ void SendPacketToNetwork(absl::string_view packet) override; // QbonePacketProcessor::StatsInterface implementation. - void OnPacketForwarded(QbonePacketProcessor::Direction direction) override {} - void OnPacketDroppedSilently( - QbonePacketProcessor::Direction direction) override {} - void OnPacketDroppedWithIcmp( - QbonePacketProcessor::Direction direction) override {} - void OnPacketDroppedWithTcpReset( - QbonePacketProcessor::Direction direction) override {} - void OnPacketDeferred(QbonePacketProcessor::Direction direction) override {} + void OnPacketForwarded(QbonePacketProcessor::Direction direction, + uint8_t traffic_class) override {} + void OnPacketDroppedSilently(QbonePacketProcessor::Direction direction, + uint8_t traffic_class) override {} + void OnPacketDroppedWithIcmp(QbonePacketProcessor::Direction direction, + uint8_t traffic_class) override {} + void OnPacketDroppedWithTcpReset(QbonePacketProcessor::Direction direction, + uint8_t traffic_class) override {} + void OnPacketDeferred(QbonePacketProcessor::Direction direction, + uint8_t traffic_class) override {} protected: // QboneSessionBase interface implementation.