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