OSDN Git Service

L2cap scheduler: Drop packets when chennel is closed
authorHansong Zhang <hsz@google.com>
Tue, 2 Feb 2021 20:20:23 +0000 (12:20 -0800)
committerHansong Zhang <hsz@google.com>
Wed, 3 Feb 2021 01:05:36 +0000 (17:05 -0800)
Bug: 179124160
Test: bluetooth_test_gd
Tag: #stability
Change-Id: I820f4440c91975986505deaf45647dbe21f5f601

gd/l2cap/internal/data_pipeline_manager.cc
gd/l2cap/internal/scheduler.h
gd/l2cap/internal/scheduler_fifo.cc
gd/l2cap/internal/scheduler_fifo.h
gd/l2cap/internal/scheduler_fifo_test.cc

index 7247e28..e3fe89b 100644 (file)
@@ -36,6 +36,7 @@ void DataPipelineManager::AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> ch
 void DataPipelineManager::DetachChannel(Cid cid) {
   ASSERT(sender_map_.find(cid) != sender_map_.end());
   sender_map_.erase(cid);
+  scheduler_->RemoveChannel(cid);
   scheduler_->SetChannelTxPriority(cid, false);
 }
 
index dce2ec6..281bf8e 100644 (file)
@@ -60,6 +60,11 @@ class Scheduler {
    */
   virtual void SetChannelTxPriority(Cid cid, bool high_priority) {}
 
+  /**
+   * Called by data controller to indicate that a channel is closed and packets should be dropped
+   */
+  virtual void RemoveChannel(Cid cid) {}
+
   virtual ~Scheduler() = default;
 };
 
index 62d94e6..110fe08 100644 (file)
@@ -57,6 +57,19 @@ void Fifo::SetChannelTxPriority(Cid cid, bool high_priority) {
   }
 }
 
+void Fifo::RemoveChannel(Cid cid) {
+  for (int i = 0; i < next_to_dequeue_and_num_packets.size(); i++) {
+    auto& channel_id_and_number_packets = next_to_dequeue_and_num_packets.front();
+    if (channel_id_and_number_packets.second != cid) {
+      next_to_dequeue_and_num_packets.push(channel_id_and_number_packets);
+    }
+    next_to_dequeue_and_num_packets.pop();
+  }
+  if (next_to_dequeue_and_num_packets.empty() && link_queue_enqueue_registered_.exchange(false)) {
+    link_queue_up_end_->UnregisterEnqueue();
+  }
+}
+
 // Invoked from some external Queue Reactable context
 std::unique_ptr<Fifo::UpperDequeue> Fifo::link_queue_enqueue_callback() {
   ASSERT(!next_to_dequeue_and_num_packets.empty());
index 6e77d9f..23a292c 100644 (file)
@@ -42,6 +42,7 @@ class Fifo : public Scheduler {
   ~Fifo();
   void OnPacketsReady(Cid cid, int number_packets) override;
   void SetChannelTxPriority(Cid cid, bool high_priority) override;
+  void RemoveChannel(Cid cid) override;
 
  private:
   DataPipelineManager* data_pipeline_manager_;
index 9ab2cb5..9a0579f 100644 (file)
@@ -138,6 +138,29 @@ TEST_F(L2capSchedulerFifoTest, prioritize_channel) {
   enqueue_.enqueued.pop();
 }
 
+TEST_F(L2capSchedulerFifoTest, remove_channel) {
+  auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'}));
+  data_controller_1_.next_packets.push(std::move(frame));
+  frame = BasicFrameBuilder::Create(2, CreateSdu({'d', 'e', 'f'}));
+  data_controller_2_.next_packets.push(std::move(frame));
+
+  EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(1)).WillRepeatedly(Return(&data_controller_1_));
+  EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(2)).WillRepeatedly(Return(&data_controller_2_));
+  EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(2));
+  fifo_->OnPacketsReady(1, 1);
+  fifo_->OnPacketsReady(2, 1);
+  fifo_->RemoveChannel(1);
+  enqueue_.run_enqueue(1);
+  auto packet1 = std::move(enqueue_.enqueued.front());
+  auto packet_view = GetPacketView(std::move(packet1));
+  auto basic_frame_view = BasicFrameView::Create(packet_view);
+  ASSERT_TRUE(basic_frame_view.IsValid());
+  ASSERT_EQ(basic_frame_view.GetChannelId(), 2);
+  auto payload = basic_frame_view.GetPayload();
+  ASSERT_EQ(std::string(payload.begin(), payload.end()), "def");
+  enqueue_.enqueued.pop();
+}
+
 }  // namespace
 }  // namespace internal
 }  // namespace l2cap