• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <base/logging.h>
18 #include <gtest/gtest.h>
19 #include <cstdint>
20 #include <queue>
21 
22 #include "hci/src/packet_fragmenter.cc"
23 #include "osi/test/AllocationTestHarness.h"
24 
25 extern void allocation_tracker_uninit(void);
26 
27 enum kPacketOrder {
28   kStart = 1,
29   kContinuation = 2,
30 };
31 
32 struct AclPacketHeader {
33   struct {
34     uint16_t handle : 12;
35     uint16_t continuation : 1;
36     uint16_t start : 1;
37     uint16_t reserved : 2;
38   } s;
39   uint16_t length;
40 
GetRawHandleAclPacketHeader41   uint16_t GetRawHandle() const { return *(uint16_t*)(this); }
42 
GetHandleAclPacketHeader43   uint16_t GetHandle() const { return s.handle; }
GetLengthAclPacketHeader44   uint16_t GetLength() const { return length; }
45 } __attribute__((packed));
46 
47 struct L2capPacketHeader {
48   uint16_t length;
49   uint16_t cid;
50 } __attribute__((packed));
51 
52 struct AclL2capPacketHeader {
53   struct AclPacketHeader acl_header;
54   struct L2capPacketHeader l2cap_header;
55 } __attribute__((packed));
56 
57 namespace {
58 
59 constexpr uint16_t kHandle = 0x123;
60 constexpr uint16_t kCid = 0x4567;
61 constexpr uint16_t kMaxPacketSize = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR) -
62                                     L2CAP_HEADER_SIZE - HCI_ACL_PREAMBLE_SIZE;
63 constexpr size_t kTypicalPacketSizes[] = {
64     1, 2, 3, 4, 8, 16, 32, 64, 127, 128, 129, 256, 1024, 2048, kMaxPacketSize};
65 constexpr size_t kNumberOfTypicalPacketSizes =
66     sizeof(kTypicalPacketSizes) / sizeof(kTypicalPacketSizes[0]);
67 
FreeBuffer(BT_HDR * bt_hdr)68 void FreeBuffer(BT_HDR* bt_hdr) { osi_free(bt_hdr); }
69 
70 struct TestMutables {
71   struct {
72     int access_count_{0};
73   } fragmented;
74   struct {
75     int access_count_{0};
76     std::queue<std::unique_ptr<BT_HDR, decltype(&FreeBuffer)>> queue;
77   } reassembled;
78   struct {
79     int access_count_{0};
80   } transmit_finished;
81 };
82 
83 TestMutables test_state_;
84 
OnFragmented(BT_HDR * packet,bool send_transmit_finished)85 void OnFragmented(BT_HDR* packet, bool send_transmit_finished) {
86   test_state_.fragmented.access_count_++;
87 }
88 
OnReassembled(BT_HDR * packet)89 void OnReassembled(BT_HDR* packet) {
90   test_state_.reassembled.access_count_++;
91   test_state_.reassembled.queue.push(
92       std::unique_ptr<BT_HDR, decltype(&FreeBuffer)>(packet, &FreeBuffer));
93 }
94 
OnTransmitFinished(BT_HDR * packet,bool all_fragments_sent)95 void OnTransmitFinished(BT_HDR* packet, bool all_fragments_sent) {
96   test_state_.transmit_finished.access_count_++;
97 }
98 
99 packet_fragmenter_callbacks_t result_callbacks = {
100     .fragmented = OnFragmented,
101     .reassembled = OnReassembled,
102     .transmit_finished = OnTransmitFinished,
103 };
104 
AclHeader(BT_HDR * packet)105 AclPacketHeader* AclHeader(BT_HDR* packet) {
106   return (AclPacketHeader*)packet->data;
107 }
L2capHeader(BT_HDR * packet)108 L2capPacketHeader* L2capHeader(BT_HDR* packet) {
109   return &((AclL2capPacketHeader*)packet->data)->l2cap_header;
110 }
111 
Data(BT_HDR * packet)112 uint8_t* Data(BT_HDR* packet) {
113   AclPacketHeader* acl_header =
114       reinterpret_cast<AclPacketHeader*>(packet->data);
115   return acl_header->s.start
116              ? (uint8_t*)(packet->data + sizeof(AclL2capPacketHeader))
117              : (uint8_t*)(packet->data + sizeof(AclPacketHeader));
118 }
119 
120 }  // namespace
121 
122 // Needed for linkage
controller_get_interface()123 const controller_t* controller_get_interface() { return nullptr; }
124 
125 /**
126  * Test class to test selected functionality in hci/src/hci_layer.cc
127  */
128 class HciPacketFragmenterTest : public AllocationTestHarness {
129  protected:
SetUp()130   void SetUp() override {
131     AllocationTestHarness::SetUp();
132     // Disable our allocation tracker to allow ASAN full range
133     allocation_tracker_uninit();
134     packet_fragmenter_ = packet_fragmenter_get_interface();
135     packet_fragmenter_->init(&result_callbacks);
136     test_state_ = TestMutables();
137   }
138 
TearDown()139   void TearDown() override {
140     FlushPartialPackets();
141     while (!test_state_.reassembled.queue.empty()) {
142       test_state_.reassembled.queue.pop();
143     }
144     packet_fragmenter_->cleanup();
145     AllocationTestHarness::TearDown();
146   }
147   const packet_fragmenter_t* packet_fragmenter_;
148 
149   // Start acl packet
AllocateL2capPacket(size_t l2cap_length,const std::vector<uint8_t> data) const150   BT_HDR* AllocateL2capPacket(size_t l2cap_length,
151                               const std::vector<uint8_t> data) const {
152     auto packet =
153         AllocateAclPacket(data.size() + sizeof(L2capPacketHeader), kStart);
154     L2capHeader(packet)->length = l2cap_length;
155     L2capHeader(packet)->cid = kCid;
156     std::copy(data.cbegin(), data.cend(), Data(packet));
157     return packet;
158   }
159 
160   // Continuation acl packet
AllocateL2capPacket(const std::vector<uint8_t> data) const161   BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
162     auto packet = AllocateAclPacket(data.size(), kContinuation);
163     std::copy(data.cbegin(), data.cend(), Data(packet));
164     return packet;
165   }
166 
CreateData(size_t size) const167   const std::vector<uint8_t> CreateData(size_t size) const {
168     CHECK(size > 0);
169     std::vector<uint8_t> v(size);
170     uint8_t sum = 0;
171     for (size_t s = 0; s < size; s++) {
172       sum += v[s] = s;
173     }
174     v[0] = (~sum + 1);  // First byte has sum complement
175     return v;
176   }
177 
178   // Verify packet integrity
VerifyData(const uint8_t * data,size_t size) const179   bool VerifyData(const uint8_t* data, size_t size) const {
180     CHECK(size > 0);
181     uint8_t sum = 0;
182     for (size_t s = 0; s < size; s++) {
183       sum += data[s];
184     }
185     return sum == 0;
186   }
187 
188  private:
AllocateAclPacket(size_t acl_length,kPacketOrder packet_order) const189   BT_HDR* AllocateAclPacket(size_t acl_length,
190                             kPacketOrder packet_order) const {
191     BT_HDR* packet = AllocatePacket(sizeof(AclPacketHeader) + acl_length,
192                                     MSG_HC_TO_STACK_HCI_ACL);
193     AclHeader(packet)->s.handle = kHandle;
194     AclHeader(packet)->length = acl_length;
195     switch (packet_order) {
196       case kStart:
197         AclHeader(packet)->s.start = 1;
198         break;
199       case kContinuation:
200         AclHeader(packet)->s.continuation = 1;
201         break;
202     }
203     return packet;
204   }
205 
AllocatePacket(size_t packet_length,uint16_t event_mask) const206   BT_HDR* AllocatePacket(size_t packet_length, uint16_t event_mask) const {
207     BT_HDR* packet =
208         static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
209     packet->event = event_mask;
210     packet->len = static_cast<uint16_t>(packet_length);
211     return packet;
212   }
213 
FlushPartialPackets() const214   void FlushPartialPackets() const {
215     while (!partial_packets.empty()) {
216       BT_HDR* partial_packet = partial_packets.at(kHandle);
217       partial_packets.erase(kHandle);
218       osi_free(partial_packet);
219     }
220   }
221 };
222 
TEST_F(HciPacketFragmenterTest,TestStruct_Handle)223 TEST_F(HciPacketFragmenterTest, TestStruct_Handle) {
224   AclPacketHeader acl_header;
225   memset(&acl_header, 0, sizeof(acl_header));
226 
227   for (uint16_t h = 0; h < UINT16_MAX; h++) {
228     acl_header.s.handle = h;
229     CHECK(acl_header.GetHandle() == (h & HANDLE_MASK));
230     CHECK(acl_header.s.continuation == 0);
231     CHECK(acl_header.s.start == 0);
232     CHECK(acl_header.s.reserved == 0);
233 
234     CHECK((acl_header.GetRawHandle() & HANDLE_MASK) == (h & HANDLE_MASK));
235     GET_BOUNDARY_FLAG(acl_header.GetRawHandle() == 0);
236   }
237 }
238 
TEST_F(HciPacketFragmenterTest,TestStruct_Continuation)239 TEST_F(HciPacketFragmenterTest, TestStruct_Continuation) {
240   AclPacketHeader acl_header;
241   memset(&acl_header, 0, sizeof(acl_header));
242 
243   for (uint16_t h = 0; h < UINT16_MAX; h++) {
244     acl_header.s.continuation = h;
245     CHECK(acl_header.GetHandle() == 0);
246     CHECK(acl_header.s.continuation == (h & 0x1));
247     CHECK(acl_header.s.start == 0);
248     CHECK(acl_header.s.reserved == 0);
249 
250     CHECK((acl_header.GetRawHandle() & HANDLE_MASK) == 0);
251     GET_BOUNDARY_FLAG(acl_header.GetRawHandle() == (h & 0x3));
252   }
253 }
254 
TEST_F(HciPacketFragmenterTest,TestStruct_Start)255 TEST_F(HciPacketFragmenterTest, TestStruct_Start) {
256   AclPacketHeader acl_header;
257   memset(&acl_header, 0, sizeof(acl_header));
258 
259   for (uint16_t h = 0; h < UINT16_MAX; h++) {
260     acl_header.s.start = h;
261     CHECK(acl_header.GetHandle() == 0);
262     CHECK(acl_header.s.continuation == 0);
263     CHECK(acl_header.s.start == (h & 0x1));
264     CHECK(acl_header.s.reserved == 0);
265 
266     CHECK((acl_header.GetRawHandle() & HANDLE_MASK) == 0);
267     GET_BOUNDARY_FLAG(acl_header.GetRawHandle() == (h & 0x3));
268   }
269 }
270 
TEST_F(HciPacketFragmenterTest,TestStruct_Reserved)271 TEST_F(HciPacketFragmenterTest, TestStruct_Reserved) {
272   AclPacketHeader acl_header;
273   memset(&acl_header, 0, sizeof(acl_header));
274 
275   for (uint16_t h = 0; h < UINT16_MAX; h++) {
276     acl_header.s.reserved = h;
277     CHECK(acl_header.GetHandle() == 0);
278     CHECK(acl_header.s.continuation == 0);
279     CHECK(acl_header.s.start == 0);
280     CHECK(acl_header.s.reserved == (h & 0x3));
281   }
282 }
TEST_F(HciPacketFragmenterTest,CreateAndVerifyPackets)283 TEST_F(HciPacketFragmenterTest, CreateAndVerifyPackets) {
284   const size_t size_check[] = {1,  2,   3,   4,   8,   16,   32,
285                                64, 127, 128, 129, 256, 1024, 0xfff0};
286   const std::vector<size_t> sizes(
287       size_check, size_check + sizeof(size_check) / sizeof(size_check[0]));
288 
289   for (const auto packet_size : sizes) {
290     const std::vector<uint8_t> data = CreateData(packet_size);
291     uint8_t buf[packet_size];
292     std::copy(data.cbegin(), data.cend(), buf);
293     CHECK(VerifyData(buf, packet_size));
294   }
295 }
296 
TEST_F(HciPacketFragmenterTest,OnePacket_Immediate)297 TEST_F(HciPacketFragmenterTest, OnePacket_Immediate) {
298   const std::vector<size_t> sizes(
299       kTypicalPacketSizes, kTypicalPacketSizes + kNumberOfTypicalPacketSizes);
300 
301   int reassembled_access_count = 0;
302   for (const auto packet_size : sizes) {
303     const std::vector<uint8_t> data = CreateData(packet_size);
304     reassemble_and_dispatch(AllocateL2capPacket(data.size(), data));
305 
306     CHECK(partial_packets.size() == 0);
307     CHECK(test_state_.reassembled.access_count_ == ++reassembled_access_count);
308     auto packet = std::move(test_state_.reassembled.queue.front());
309     test_state_.reassembled.queue.pop();
310     CHECK(VerifyData(Data(packet.get()), packet_size));
311   }
312 }
313 
TEST_F(HciPacketFragmenterTest,OnePacket_ImmediateTooBig)314 TEST_F(HciPacketFragmenterTest, OnePacket_ImmediateTooBig) {
315   const size_t packet_size = kMaxPacketSize + 1;
316   const std::vector<uint8_t> data = CreateData(packet_size);
317   reassemble_and_dispatch(AllocateL2capPacket(data.size(), data));
318 
319   CHECK(partial_packets.size() == 0);
320   CHECK(test_state_.reassembled.access_count_ == 0);
321 }
322 
TEST_F(HciPacketFragmenterTest,ThreePackets_Immediate)323 TEST_F(HciPacketFragmenterTest, ThreePackets_Immediate) {
324   const size_t packet_size = 512;
325   const std::vector<uint8_t> data = CreateData(packet_size);
326   reassemble_and_dispatch(AllocateL2capPacket(data.size(), data));
327   reassemble_and_dispatch(AllocateL2capPacket(data.size(), data));
328   reassemble_and_dispatch(AllocateL2capPacket(data.size(), data));
329   CHECK(partial_packets.size() == 0);
330   CHECK(test_state_.reassembled.access_count_ == 3);
331 }
332 
TEST_F(HciPacketFragmenterTest,OnePacket_SplitTwo)333 TEST_F(HciPacketFragmenterTest, OnePacket_SplitTwo) {
334   const std::vector<size_t> sizes(
335       kTypicalPacketSizes, kTypicalPacketSizes + kNumberOfTypicalPacketSizes);
336 
337   int reassembled_access_count = 0;
338   for (auto packet_size : sizes) {
339     const std::vector<uint8_t> data = CreateData(packet_size);
340     const std::vector<uint8_t> part1(data.cbegin(),
341                                      data.cbegin() + packet_size / 2);
342     reassemble_and_dispatch(AllocateL2capPacket(data.size(), part1));
343 
344     CHECK(partial_packets.size() == 1);
345     CHECK(test_state_.reassembled.access_count_ == reassembled_access_count);
346 
347     const std::vector<uint8_t> part2(data.cbegin() + packet_size / 2,
348                                      data.cend());
349     reassemble_and_dispatch(AllocateL2capPacket(part2));
350 
351     CHECK(partial_packets.size() == 0);
352     CHECK(test_state_.reassembled.access_count_ == ++reassembled_access_count);
353 
354     auto packet = std::move(test_state_.reassembled.queue.front());
355     test_state_.reassembled.queue.pop();
356     CHECK(VerifyData(Data(packet.get()), packet_size));
357   }
358 }
359 
TEST_F(HciPacketFragmenterTest,OnePacket_SplitALot)360 TEST_F(HciPacketFragmenterTest, OnePacket_SplitALot) {
361   const size_t packet_size = 512;
362   const size_t stride = 2;
363 
364   const std::vector<uint8_t> data = CreateData(packet_size);
365   const std::vector<uint8_t> first_part(data.cbegin(), data.cbegin() + stride);
366   reassemble_and_dispatch(AllocateL2capPacket(data.size(), first_part));
367   CHECK(partial_packets.size() == 1);
368 
369   for (size_t i = 2; i < packet_size - stride; i += stride) {
370     const std::vector<uint8_t> middle_part(data.cbegin() + i,
371                                            data.cbegin() + i + stride);
372     reassemble_and_dispatch(AllocateL2capPacket(middle_part));
373   }
374   CHECK(partial_packets.size() == 1);
375   CHECK(test_state_.reassembled.access_count_ == 0);
376 
377   const std::vector<uint8_t> last_part(data.cbegin() + packet_size - stride,
378                                        data.cend());
379   reassemble_and_dispatch(AllocateL2capPacket(last_part));
380 
381   CHECK(partial_packets.size() == 0);
382   CHECK(test_state_.reassembled.access_count_ == 1);
383   auto packet = std::move(test_state_.reassembled.queue.front());
384   CHECK(VerifyData(Data(packet.get()), packet_size));
385 }
386 
TEST_F(HciPacketFragmenterTest,TwoPacket_InvalidLength)387 TEST_F(HciPacketFragmenterTest, TwoPacket_InvalidLength) {
388   const size_t packet_size = UINT16_MAX;
389   const std::vector<uint8_t> data = CreateData(packet_size);
390   const std::vector<uint8_t> first_part(data.cbegin(),
391                                         data.cbegin() + packet_size / 2);
392   reassemble_and_dispatch(AllocateL2capPacket(data.size(), first_part));
393 
394   CHECK(partial_packets.size() == 0);
395   CHECK(test_state_.reassembled.access_count_ == 0);
396 
397   const std::vector<uint8_t> second_part(data.cbegin() + packet_size / 2,
398                                          data.cend());
399   reassemble_and_dispatch(AllocateL2capPacket(second_part));
400 
401   CHECK(partial_packets.size() == 0);
402   CHECK(test_state_.reassembled.access_count_ == 0);
403 }
404 
TEST_F(HciPacketFragmenterTest,TwoPacket_HugeBogusSecond)405 TEST_F(HciPacketFragmenterTest, TwoPacket_HugeBogusSecond) {
406   const size_t packet_size = kMaxPacketSize;
407   const std::vector<uint8_t> data = CreateData(UINT16_MAX);
408   const std::vector<uint8_t> first_part(data.cbegin(),
409                                         data.cbegin() + packet_size - 1);
410   reassemble_and_dispatch(AllocateL2capPacket(packet_size, first_part));
411 
412   CHECK(partial_packets.size() == 1);
413   CHECK(test_state_.reassembled.access_count_ == 0);
414 
415   const std::vector<uint8_t> second_part(data.cbegin() + packet_size - 1,
416                                          data.cend());
417   reassemble_and_dispatch(AllocateL2capPacket(second_part));
418 
419   CHECK(partial_packets.size() == 0);
420   CHECK(test_state_.reassembled.access_count_ == 1);
421 }
422