Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a7def0c authored by Hansong Zhang's avatar Hansong Zhang
Browse files

L2CAP: Decouple scheduler and segmenter

Scheduler is used for enqueuing PDUs from segmenters to link queue end.
Segmenter is used for dequeuing SDUs from channels to scheduler.
Segmenter needs to handle converting PDUs into SDUs.

Bug: 144375926
Test: run_cert.sh and bluetooth_test_gd
Change-Id: Ia4a1707d7e0147f9f63c137e62d15ecdc877a813
parent cda9f07b
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@ filegroup {
        "classic/internal/link_manager.cc",
        "classic/internal/signalling_manager.cc",
        "classic/l2cap_classic_module.cc",
        "internal/scheduler_fifo.cc",
        "internal/reassembler.cc",
        "internal/scheduler_fifo.cc",
        "internal/segmenter.cc",
        "le/internal/fixed_channel_impl.cc",
        "le/internal/fixed_channel_service_manager_impl.cc",
        "le/internal/link_manager.cc",
@@ -42,6 +43,7 @@ filegroup {
        "internal/fixed_channel_allocator_test.cc",
        "internal/reassembler_test.cc",
        "internal/scheduler_fifo_test.cc",
        "internal/segmenter_test.cc",
        "l2cap_packet_test.cc",
        "le/internal/fixed_channel_impl_test.cc",
        "le/internal/fixed_channel_service_manager_test.cc",
+5 −0
Original line number Diff line number Diff line
@@ -59,6 +59,11 @@ class Scheduler {
   */
  virtual void DetachChannel(Cid cid) {}

  /**
   * Callback from the segmenter to indicate that the scheduler could dequeue number_packets from it
   */
  virtual void NotifyPacketsReady(Cid cid, int number_packets) {}

  virtual ~Scheduler() = default;
};

+21 −42
Original line number Diff line number Diff line
@@ -28,34 +28,40 @@ Fifo::Fifo(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler)
}

Fifo::~Fifo() {
  channel_queue_end_map_.clear();
  segmenter_map_.clear();
  if (link_queue_enqueue_registered_) {
    link_queue_up_end_->UnregisterEnqueue();
  }
}

void Fifo::AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) {
  ASSERT(channel_queue_end_map_.find(cid) == channel_queue_end_map_.end());
  channel_queue_end_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
  ASSERT(segmenter_map_.find(cid) == segmenter_map_.end());
  segmenter_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
                         std::forward_as_tuple(handler_, channel_down_end, this, cid, remote_cid));
}

void Fifo::DetachChannel(Cid cid) {
  ASSERT(channel_queue_end_map_.find(cid) != channel_queue_end_map_.end());
  channel_queue_end_map_.erase(cid);
  ASSERT(segmenter_map_.find(cid) != segmenter_map_.end());
  segmenter_map_.erase(cid);
}

void Fifo::NotifyPacketsReady(Cid cid, int number_packets) {
  next_to_dequeue_and_num_packets.push(std::make_pair(cid, number_packets));
  try_register_link_queue_enqueue();
}

std::unique_ptr<Fifo::UpperDequeue> Fifo::link_queue_enqueue_callback() {
  ASSERT(!next_to_dequeue_.empty());
  auto channel_id = next_to_dequeue_.front();
  next_to_dequeue_.pop();
  auto& pdu_buffer = channel_queue_end_map_.find(channel_id)->second.pdu_buffer_;
  auto packet = std::move(pdu_buffer.front());
  pdu_buffer.pop();
  if (pdu_buffer.empty()) {
    channel_queue_end_map_.find(channel_id)->second.try_register_dequeue();
  ASSERT(!next_to_dequeue_and_num_packets.empty());
  auto& channel_id_and_number_packets = next_to_dequeue_and_num_packets.front();
  auto channel_id = channel_id_and_number_packets.first;
  channel_id_and_number_packets.second--;
  if (channel_id_and_number_packets.second == 0) {
    next_to_dequeue_and_num_packets.pop();
  }
  if (next_to_dequeue_.empty()) {
  auto packet = segmenter_map_.find(channel_id)->second.GetNextPacket();

  segmenter_map_.find(channel_id)->second.NotifyPacketSent();
  if (next_to_dequeue_and_num_packets.empty()) {
    link_queue_up_end_->UnregisterEnqueue();
    link_queue_enqueue_registered_ = false;
  }
@@ -71,33 +77,6 @@ void Fifo::try_register_link_queue_enqueue() {
  link_queue_enqueue_registered_ = true;
}

void Fifo::ChannelQueueEndAndBuffer::try_register_dequeue() {
  if (is_dequeue_registered_) {
    return;
  }
  queue_end_->RegisterDequeue(
      handler_, common::Bind(&Fifo::ChannelQueueEndAndBuffer::dequeue_callback, common::Unretained(this)));
  is_dequeue_registered_ = true;
}

void Fifo::ChannelQueueEndAndBuffer::dequeue_callback() {
  auto packet = queue_end_->TryDequeue();
  ASSERT(packet != nullptr);
  // TODO(hsz): Construct PDU(s) according to channel mode.
  auto pdu = BasicFrameBuilder::Create(remote_channel_id_, std::move(packet));
  pdu_buffer_.emplace(std::move(pdu));
  queue_end_->UnregisterDequeue();
  is_dequeue_registered_ = false;
  scheduler_->next_to_dequeue_.push(channel_id_);
  scheduler_->try_register_link_queue_enqueue();
}

Fifo::ChannelQueueEndAndBuffer::~ChannelQueueEndAndBuffer() {
  if (is_dequeue_registered_) {
    queue_end_->UnregisterDequeue();
  }
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
+4 −25
Original line number Diff line number Diff line
@@ -23,10 +23,9 @@
#include "common/bind.h"
#include "l2cap/cid.h"
#include "l2cap/internal/scheduler.h"
#include "l2cap/internal/segmenter.h"
#include "os/handler.h"
#include "os/queue.h"
#include "packet/base_packet_builder.h"
#include "packet/packet_view.h"

namespace bluetooth {
namespace l2cap {
@@ -38,33 +37,13 @@ class Fifo : public Scheduler {
  ~Fifo() override;
  void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) override;
  void DetachChannel(Cid cid) override;
  void NotifyPacketsReady(Cid cid, int number_packets) override;

 private:
  LowerQueueUpEnd* link_queue_up_end_;
  os::Handler* handler_;

  struct ChannelQueueEndAndBuffer {
    ChannelQueueEndAndBuffer(os::Handler* handler, UpperQueueDownEnd* queue_end, Fifo* scheduler, Cid channel_id,
                             Cid remote_channel_id)
        : handler_(handler), queue_end_(queue_end), scheduler_(scheduler), channel_id_(channel_id),
          remote_channel_id_(remote_channel_id) {
      try_register_dequeue();
    }
    os::Handler* handler_;
    UpperQueueDownEnd* queue_end_;
    std::queue<std::unique_ptr<UpperDequeue>> pdu_buffer_;
    Fifo* scheduler_;
    const Cid channel_id_;
    const Cid remote_channel_id_;
    bool is_dequeue_registered_ = false;

    void try_register_dequeue();
    void dequeue_callback();
    ~ChannelQueueEndAndBuffer();
  };

  std::unordered_map<Cid, ChannelQueueEndAndBuffer> channel_queue_end_map_;
  std::queue<Cid> next_to_dequeue_;
  std::unordered_map<Cid, Segmenter> segmenter_map_;
  std::queue<std::pair<Cid, int>> next_to_dequeue_and_num_packets;

  bool link_queue_enqueue_registered_ = false;
  void try_register_link_queue_enqueue();
+0 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#include <gtest/gtest.h>
#include <future>

#include "l2cap/l2cap_packets.h"
#include "os/handler.h"
#include "os/queue.h"
#include "os/thread.h"
Loading