xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/qbone/qbone_packet_processor.h"
6 
7 #include <utility>
8 
9 #include "absl/strings/string_view.h"
10 #include "quiche/quic/platform/api/quic_test.h"
11 #include "quiche/quic/qbone/qbone_packet_processor_test_tools.h"
12 #include "quiche/common/quiche_text_utils.h"
13 
14 namespace quic::test {
15 namespace {
16 
17 using Direction = QbonePacketProcessor::Direction;
18 using ProcessingResult = QbonePacketProcessor::ProcessingResult;
19 using OutputInterface = QbonePacketProcessor::OutputInterface;
20 using ::testing::_;
21 using ::testing::Eq;
22 using ::testing::Invoke;
23 using ::testing::Return;
24 using ::testing::WithArgs;
25 
26 // clang-format off
27 static const char kReferenceClientPacketData[] = {
28     // IPv6 with zero TOS and flow label.
29     0x60, 0x00, 0x00, 0x00,
30     // Payload size is 8 bytes.
31     0x00, 0x08,
32     // Next header is UDP
33     17,
34     // TTL is 50.
35     50,
36     // IP address of the sender is fd00:0:0:1::1
37     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
38     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
39     // IP address of the receiver is fd00:0:0:5::1
40     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
41     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
42     // Source port 12345
43     0x30, 0x39,
44     // Destination port 443
45     0x01, 0xbb,
46     // UDP content length is zero
47     0x00, 0x00,
48     // Checksum is not actually checked in any of the tests, so we leave it as
49     // zero
50     0x00, 0x00,
51 };
52 
53 static const char kReferenceClientPacketDataAF4[] = {
54     // IPv6 with 0x80 TOS and zero flow label.
55     0x68, 0x00, 0x00, 0x00,
56     // Payload size is 8 bytes.
57     0x00, 0x08,
58     // Next header is UDP
59     17,
60     // TTL is 50.
61     50,
62     // IP address of the sender is fd00:0:0:1::1
63     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
65     // IP address of the receiver is fd00:0:0:5::1
66     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
67     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
68     // Source port 12345
69     0x30, 0x39,
70     // Destination port 443
71     0x01, 0xbb,
72     // UDP content length is zero
73     0x00, 0x00,
74     // Checksum is not actually checked in any of the tests, so we leave it as
75     // zero
76     0x00, 0x00,
77 };
78 
79 static const char kReferenceClientPacketDataAF3[] = {
80     // IPv6 with 0x60 TOS and zero flow label.
81     0x66, 0x00, 0x00, 0x00,
82     // Payload size is 8 bytes.
83     0x00, 0x08,
84     // Next header is UDP
85     17,
86     // TTL is 50.
87     50,
88     // IP address of the sender is fd00:0:0:1::1
89     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
90     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
91     // IP address of the receiver is fd00:0:0:5::1
92     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
93     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
94     // Source port 12345
95     0x30, 0x39,
96     // Destination port 443
97     0x01, 0xbb,
98     // UDP content length is zero
99     0x00, 0x00,
100     // Checksum is not actually checked in any of the tests, so we leave it as
101     // zero
102     0x00, 0x00,
103 };
104 
105 static const char kReferenceClientPacketDataAF2[] = {
106     // IPv6 with 0x40 TOS and zero flow label.
107     0x64, 0x00, 0x00, 0x00,
108     // Payload size is 8 bytes.
109     0x00, 0x08,
110     // Next header is UDP
111     17,
112     // TTL is 50.
113     50,
114     // IP address of the sender is fd00:0:0:1::1
115     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
116     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
117     // IP address of the receiver is fd00:0:0:5::1
118     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
119     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
120     // Source port 12345
121     0x30, 0x39,
122     // Destination port 443
123     0x01, 0xbb,
124     // UDP content length is zero
125     0x00, 0x00,
126     // Checksum is not actually checked in any of the tests, so we leave it as
127     // zero
128     0x00, 0x00,
129 };
130 
131 static const char kReferenceClientPacketDataAF1[] = {
132     // IPv6 with 0x20 TOS and zero flow label.
133     0x62, 0x00, 0x00, 0x00,
134     // Payload size is 8 bytes.
135     0x00, 0x08,
136     // Next header is UDP
137     17,
138     // TTL is 50.
139     50,
140     // IP address of the sender is fd00:0:0:1::1
141     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
142     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
143     // IP address of the receiver is fd00:0:0:5::1
144     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
145     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
146     // Source port 12345
147     0x30, 0x39,
148     // Destination port 443
149     0x01, 0xbb,
150     // UDP content length is zero
151     0x00, 0x00,
152     // Checksum is not actually checked in any of the tests, so we leave it as
153     // zero
154     0x00, 0x00,
155 };
156 
157 static const char kReferenceNetworkPacketData[] = {
158     // IPv6 with zero TOS and flow label.
159     0x60, 0x00, 0x00, 0x00,
160     // Payload size is 8 bytes.
161     0x00, 0x08,
162     // Next header is UDP
163     17,
164     // TTL is 50.
165     50,
166     // IP address of the sender is fd00:0:0:5::1
167     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
168     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
169     // IP address of the receiver is fd00:0:0:1::1
170     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
171     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
172     // Source port 443
173     0x01, 0xbb,
174     // Destination port 12345
175     0x30, 0x39,
176     // UDP content length is zero
177     0x00, 0x00,
178     // Checksum is not actually checked in any of the tests, so we leave it as
179     // zero
180     0x00, 0x00,
181 };
182 
183 static const char kReferenceClientSubnetPacketData[] = {
184     // IPv6 with zero TOS and flow label.
185     0x60, 0x00, 0x00, 0x00,
186     // Payload size is 8 bytes.
187     0x00, 0x08,
188     // Next header is UDP
189     17,
190     // TTL is 50.
191     50,
192     // IP address of the sender is fd00:0:0:2::1, which is within the /62 of the
193     // client.
194     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
195     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
196     // IP address of the receiver is fd00:0:0:5::1
197     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
198     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
199     // Source port 12345
200     0x30, 0x39,
201     // Destination port 443
202     0x01, 0xbb,
203     // UDP content length is zero
204     0x00, 0x00,
205     // Checksum is not actually checked in any of the tests, so we leave it as
206     // zero
207     0x00, 0x00,
208 };
209 
210 static const char kReferenceEchoRequestData[] = {
211     // IPv6 with zero TOS and flow label.
212     0x60, 0x00, 0x00, 0x00,
213     // Payload size is 64 bytes.
214     0x00, 64,
215     // Next header is ICMP
216     58,
217     // TTL is 127.
218     127,
219     // IP address of the sender is fd00:0:0:1::1
220     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
221     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
222     // IP address of the receiver is fe80::71:626f:6e6f
223     0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224     0x00, 0x00, 0x00, 0x71, 0x62, 0x6f, 0x6e, 0x6f,
225     // ICMP Type ping request
226     128,
227     // ICMP Code 0
228     0,
229     // Checksum is not actually checked in any of the tests, so we leave it as
230     // zero
231     0x00, 0x00,
232     // ICMP Identifier (0xcafe to be memorable)
233     0xca, 0xfe,
234     // Sequence number
235     0x00, 0x01,
236     // Data, starting with unix timeval then 0x10..0x37
237     0x67, 0x37, 0x8a, 0x63, 0x00, 0x00, 0x00, 0x00,
238     0x96, 0x58, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
239     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
240     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
241     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
242     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
243     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
244 };
245 
246 static const char kReferenceEchoReplyData[] = {
247     // IPv6 with zero TOS and flow label.
248     0x60, 0x00, 0x00, 0x00,
249     // Payload size is 64 bytes.
250     0x00, 64,
251     // Next header is ICMP
252     58,
253     // TTL is 255.
254     255,
255     // IP address of the sender is fd00:4:0:1::1
256     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
257     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
258     // IP address of the receiver is fd00:0:0:1::1
259     0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
260     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
261     // ICMP Type ping reply
262     129,
263     // ICMP Code 0
264     0,
265     // Checksum
266     0x66, 0xb6,
267     // ICMP Identifier (0xcafe to be memorable)
268     0xca, 0xfe,
269     // Sequence number
270     0x00, 0x01,
271     // Data, starting with unix timeval then 0x10..0x37
272     0x67, 0x37, 0x8a, 0x63, 0x00, 0x00, 0x00, 0x00,
273     0x96, 0x58, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
274     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
275     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
276     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
277     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
278     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
279 };
280 
281 // clang-format on
282 
283 static const absl::string_view kReferenceClientPacket(
284     kReferenceClientPacketData, ABSL_ARRAYSIZE(kReferenceClientPacketData));
285 
286 static const absl::string_view kReferenceClientPacketAF4(
287     kReferenceClientPacketDataAF4,
288     ABSL_ARRAYSIZE(kReferenceClientPacketDataAF4));
289 static const absl::string_view kReferenceClientPacketAF3(
290     kReferenceClientPacketDataAF3,
291     ABSL_ARRAYSIZE(kReferenceClientPacketDataAF3));
292 static const absl::string_view kReferenceClientPacketAF2(
293     kReferenceClientPacketDataAF2,
294     ABSL_ARRAYSIZE(kReferenceClientPacketDataAF2));
295 static const absl::string_view kReferenceClientPacketAF1(
296     kReferenceClientPacketDataAF1,
297     ABSL_ARRAYSIZE(kReferenceClientPacketDataAF1));
298 
299 static const absl::string_view kReferenceNetworkPacket(
300     kReferenceNetworkPacketData, ABSL_ARRAYSIZE(kReferenceNetworkPacketData));
301 
302 static const absl::string_view kReferenceClientSubnetPacket(
303     kReferenceClientSubnetPacketData,
304     ABSL_ARRAYSIZE(kReferenceClientSubnetPacketData));
305 
306 static const absl::string_view kReferenceEchoRequest(
307     kReferenceEchoRequestData, ABSL_ARRAYSIZE(kReferenceEchoRequestData));
308 
309 MATCHER_P(IsIcmpMessage, icmp_type,
310           "Checks whether the argument is an ICMP message of supplied type") {
311   if (arg.size() < kTotalICMPv6HeaderSize) {
312     return false;
313   }
314 
315   return arg[40] == icmp_type;
316 }
317 
318 class MockPacketFilter : public QbonePacketProcessor::Filter {
319  public:
320   MOCK_METHOD(ProcessingResult, FilterPacket,
321               (Direction, absl::string_view, absl::string_view, icmp6_hdr*,
322                OutputInterface*),
323               (override));
324 };
325 
326 class QbonePacketProcessorTest : public QuicTest {
327  protected:
QbonePacketProcessorTest()328   QbonePacketProcessorTest() {
329     QUICHE_CHECK(client_ip_.FromString("fd00:0:0:1::1"));
330     QUICHE_CHECK(self_ip_.FromString("fd00:0:0:4::1"));
331     QUICHE_CHECK(network_ip_.FromString("fd00:0:0:5::1"));
332 
333     processor_ = std::make_unique<QbonePacketProcessor>(
334         self_ip_, client_ip_, /*client_ip_subnet_length=*/62, &output_,
335         &stats_);
336 
337     // Ignore calls to RecordThroughput
338     EXPECT_CALL(stats_, RecordThroughput(_, _, _)).WillRepeatedly(Return());
339   }
340 
SendPacketFromClient(absl::string_view packet)341   void SendPacketFromClient(absl::string_view packet) {
342     std::string packet_buffer(packet.data(), packet.size());
343     processor_->ProcessPacket(&packet_buffer, Direction::FROM_OFF_NETWORK);
344   }
345 
SendPacketFromNetwork(absl::string_view packet)346   void SendPacketFromNetwork(absl::string_view packet) {
347     std::string packet_buffer(packet.data(), packet.size());
348     processor_->ProcessPacket(&packet_buffer, Direction::FROM_NETWORK);
349   }
350 
351   QuicIpAddress client_ip_;
352   QuicIpAddress self_ip_;
353   QuicIpAddress network_ip_;
354 
355   std::unique_ptr<QbonePacketProcessor> processor_;
356   testing::StrictMock<MockPacketProcessorOutput> output_;
357   testing::StrictMock<MockPacketProcessorStats> stats_;
358 };
359 
TEST_F(QbonePacketProcessorTest,EmptyPacket)360 TEST_F(QbonePacketProcessorTest, EmptyPacket) {
361   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _));
362   EXPECT_CALL(stats_, RecordThroughput(0, Direction::FROM_OFF_NETWORK, _));
363   SendPacketFromClient("");
364 
365   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK, _));
366   EXPECT_CALL(stats_, RecordThroughput(0, Direction::FROM_NETWORK, _));
367   SendPacketFromNetwork("");
368 }
369 
TEST_F(QbonePacketProcessorTest,RandomGarbage)370 TEST_F(QbonePacketProcessorTest, RandomGarbage) {
371   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _));
372   SendPacketFromClient(std::string(1280, 'a'));
373 
374   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK, _));
375   SendPacketFromNetwork(std::string(1280, 'a'));
376 }
377 
TEST_F(QbonePacketProcessorTest,RandomGarbageWithCorrectLengthFields)378 TEST_F(QbonePacketProcessorTest, RandomGarbageWithCorrectLengthFields) {
379   std::string packet(40, 'a');
380   packet[4] = 0;
381   packet[5] = 0;
382 
383   EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK, _));
384   EXPECT_CALL(output_, SendPacketToClient(IsIcmpMessage(ICMP6_DST_UNREACH)));
385   SendPacketFromClient(packet);
386 }
387 
TEST_F(QbonePacketProcessorTest,GoodPacketFromClient)388 TEST_F(QbonePacketProcessorTest, GoodPacketFromClient) {
389   EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK, _));
390   EXPECT_CALL(output_, SendPacketToNetwork(_));
391   SendPacketFromClient(kReferenceClientPacket);
392 }
393 
TEST_F(QbonePacketProcessorTest,GoodPacketFromClientSubnet)394 TEST_F(QbonePacketProcessorTest, GoodPacketFromClientSubnet) {
395   EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK, _));
396   EXPECT_CALL(output_, SendPacketToNetwork(_));
397   SendPacketFromClient(kReferenceClientSubnetPacket);
398 }
399 
TEST_F(QbonePacketProcessorTest,GoodPacketFromNetwork)400 TEST_F(QbonePacketProcessorTest, GoodPacketFromNetwork) {
401   EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_NETWORK, _));
402   EXPECT_CALL(output_, SendPacketToClient(_));
403   SendPacketFromNetwork(kReferenceNetworkPacket);
404 }
405 
TEST_F(QbonePacketProcessorTest,GoodPacketFromNetworkWrongDirection)406 TEST_F(QbonePacketProcessorTest, GoodPacketFromNetworkWrongDirection) {
407   EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK, _));
408   EXPECT_CALL(output_, SendPacketToClient(IsIcmpMessage(ICMP6_DST_UNREACH)));
409   SendPacketFromClient(kReferenceNetworkPacket);
410 }
411 
TEST_F(QbonePacketProcessorTest,TtlExpired)412 TEST_F(QbonePacketProcessorTest, TtlExpired) {
413   std::string packet(kReferenceNetworkPacket);
414   packet[7] = 1;
415 
416   EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK, _));
417   EXPECT_CALL(output_, SendPacketToNetwork(IsIcmpMessage(ICMP6_TIME_EXCEEDED)));
418   SendPacketFromNetwork(packet);
419 }
420 
TEST_F(QbonePacketProcessorTest,UnknownProtocol)421 TEST_F(QbonePacketProcessorTest, UnknownProtocol) {
422   std::string packet(kReferenceNetworkPacket);
423   packet[6] = IPPROTO_SCTP;
424 
425   EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK, _));
426   EXPECT_CALL(output_, SendPacketToNetwork(IsIcmpMessage(ICMP6_PARAM_PROB)));
427   SendPacketFromNetwork(packet);
428 }
429 
TEST_F(QbonePacketProcessorTest,FilterFromClient)430 TEST_F(QbonePacketProcessorTest, FilterFromClient) {
431   auto filter = std::make_unique<MockPacketFilter>();
432   EXPECT_CALL(*filter, FilterPacket(_, _, _, _, _))
433       .WillRepeatedly(Return(ProcessingResult::SILENT_DROP));
434   processor_->set_filter(std::move(filter));
435 
436   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _));
437   SendPacketFromClient(kReferenceClientPacket);
438 }
439 
440 class TestFilter : public QbonePacketProcessor::Filter {
441  public:
TestFilter(QuicIpAddress client_ip,QuicIpAddress network_ip)442   TestFilter(QuicIpAddress client_ip, QuicIpAddress network_ip)
443       : client_ip_(client_ip), network_ip_(network_ip) {}
FilterPacket(Direction direction,absl::string_view full_packet,absl::string_view payload,icmp6_hdr * icmp_header,OutputInterface * output)444   ProcessingResult FilterPacket(Direction direction,
445                                 absl::string_view full_packet,
446                                 absl::string_view payload,
447                                 icmp6_hdr* icmp_header,
448                                 OutputInterface* output) override {
449     EXPECT_EQ(kIPv6HeaderSize, full_packet.size() - payload.size());
450     EXPECT_EQ(IPPROTO_UDP, TransportProtocolFromHeader(full_packet));
451     EXPECT_EQ(client_ip_, SourceIpFromHeader(full_packet));
452     EXPECT_EQ(network_ip_, DestinationIpFromHeader(full_packet));
453 
454     last_tos_ = QbonePacketProcessor::TrafficClassFromHeader(full_packet);
455     called_++;
456     return ProcessingResult::SILENT_DROP;
457   }
458 
called() const459   int called() const { return called_; }
last_tos() const460   uint8_t last_tos() const { return last_tos_; }
461 
462  private:
463   int called_ = 0;
464   uint8_t last_tos_ = 0;
465 
466   QuicIpAddress client_ip_;
467   QuicIpAddress network_ip_;
468 };
469 
470 // Verify that the parameters are passed correctly into the filter, and that the
471 // helper functions of the filter class work.
TEST_F(QbonePacketProcessorTest,FilterHelperFunctions)472 TEST_F(QbonePacketProcessorTest, FilterHelperFunctions) {
473   auto filter_owned = std::make_unique<TestFilter>(client_ip_, network_ip_);
474   TestFilter* filter = filter_owned.get();
475   processor_->set_filter(std::move(filter_owned));
476 
477   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _));
478   SendPacketFromClient(kReferenceClientPacket);
479   ASSERT_EQ(1, filter->called());
480 }
481 
TEST_F(QbonePacketProcessorTest,FilterHelperFunctionsTOS)482 TEST_F(QbonePacketProcessorTest, FilterHelperFunctionsTOS) {
483   auto filter_owned = std::make_unique<TestFilter>(client_ip_, network_ip_);
484   processor_->set_filter(std::move(filter_owned));
485 
486   EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK, _))
487       .Times(testing::AnyNumber());
488   EXPECT_CALL(stats_, RecordThroughput(kReferenceClientPacket.size(),
489                                        Direction::FROM_OFF_NETWORK, 0));
490   SendPacketFromClient(kReferenceClientPacket);
491 
492   EXPECT_CALL(stats_, RecordThroughput(kReferenceClientPacketAF4.size(),
493                                        Direction::FROM_OFF_NETWORK, 0x80));
494   SendPacketFromClient(kReferenceClientPacketAF4);
495 
496   EXPECT_CALL(stats_, RecordThroughput(kReferenceClientPacketAF3.size(),
497                                        Direction::FROM_OFF_NETWORK, 0x60));
498   SendPacketFromClient(kReferenceClientPacketAF3);
499 
500   EXPECT_CALL(stats_, RecordThroughput(kReferenceClientPacketAF2.size(),
501                                        Direction::FROM_OFF_NETWORK, 0x40));
502   SendPacketFromClient(kReferenceClientPacketAF2);
503 
504   EXPECT_CALL(stats_, RecordThroughput(kReferenceClientPacketAF1.size(),
505                                        Direction::FROM_OFF_NETWORK, 0x20));
506   SendPacketFromClient(kReferenceClientPacketAF1);
507 }
508 
TEST_F(QbonePacketProcessorTest,Icmp6EchoResponseHasRightPayload)509 TEST_F(QbonePacketProcessorTest, Icmp6EchoResponseHasRightPayload) {
510   auto filter = std::make_unique<MockPacketFilter>();
511   EXPECT_CALL(*filter, FilterPacket(_, _, _, _, _))
512       .WillOnce(WithArgs<2, 3>(
513           Invoke([](absl::string_view payload, icmp6_hdr* icmp_header) {
514             icmp_header->icmp6_type = ICMP6_ECHO_REPLY;
515             icmp_header->icmp6_code = 0;
516             auto* request_header =
517                 reinterpret_cast<const icmp6_hdr*>(payload.data());
518             icmp_header->icmp6_id = request_header->icmp6_id;
519             icmp_header->icmp6_seq = request_header->icmp6_seq;
520             return ProcessingResult::ICMP;
521           })));
522   processor_->set_filter(std::move(filter));
523 
524   EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK, _));
525   EXPECT_CALL(output_, SendPacketToClient(_))
526       .WillOnce(Invoke([](absl::string_view packet) {
527         // Explicit conversion because otherwise it is treated as a null
528         // terminated string.
529         absl::string_view expected = absl::string_view(
530             kReferenceEchoReplyData, sizeof(kReferenceEchoReplyData));
531 
532         EXPECT_THAT(packet, Eq(expected));
533         QUIC_LOG(INFO) << "ICMP response:\n"
534                        << quiche::QuicheTextUtils::HexDump(packet);
535       }));
536   SendPacketFromClient(kReferenceEchoRequest);
537 }
538 
539 }  // namespace
540 }  // namespace quic::test
541