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