Commit 43de309b authored by Jonathan Rico's avatar Jonathan Rico Committed by Alberto Escolar
Browse files

Bluetooth: l2cap: Remove (net/buf) frag support



It's needless complexity, and the terminology clashes with
Bluetooth (HCI frags).

It has one user, IPSP, that is going away soon.

Removing frag support will allow a future optimization, removing the
need for HCI and L2CAP fragment buffer pools, saving memory.

Signed-off-by: default avatarJonathan Rico <jonathan.rico@nordicsemi.no>
parent 8acc6a96
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -572,6 +572,8 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan);
 *  Regarding to first input parameter, to get details see reference description
 *  to bt_l2cap_chan_connect() API above.
 *
 *  Network buffer fragments (ie `buf->frags`) are not supported.
 *
 *  When sending L2CAP data over an BR/EDR connection the application is sending
 *  L2CAP PDUs. The application is required to have reserved
 *  @ref BT_L2CAP_CHAN_SEND_RESERVE bytes in the buffer before sending.
+23 −35
Original line number Diff line number Diff line
@@ -637,7 +637,7 @@ int bt_l2cap_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *buf,
{
	struct bt_l2cap_hdr *hdr;

	LOG_DBG("conn %p cid %u len %zu", conn, cid, net_buf_frags_len(buf));
	LOG_DBG("conn %p cid %u len %zu", conn, cid, buf->len);

	hdr = net_buf_push(buf, sizeof(*hdr));
	hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
@@ -893,7 +893,7 @@ static struct net_buf *l2cap_chan_le_get_tx_buf(struct bt_l2cap_le_chan *ch)
}

static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
				  struct net_buf **buf);
				  struct net_buf *buf);

static void l2cap_chan_tx_process(struct k_work *work)
{
@@ -911,7 +911,7 @@ static void l2cap_chan_tx_process(struct k_work *work)
		 */
		LOG_DBG("chan %p buf %p", ch, buf);

		ret = l2cap_chan_le_send_sdu(ch, &buf);
		ret = l2cap_chan_le_send_sdu(ch, buf);
		if (ret < 0) {
			if (ret == -EAGAIN) {
				ch->tx_buf = buf;
@@ -1945,11 +1945,10 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch,
	len = seg->len - sdu_hdr_len;

	/* SDU will be considered sent when there is no data left in the
	 * buffers, or if there will be no data left, if we are sending `buf`
	 * buffer, or if there will be no data left, if we are sending `buf`
	 * directly.
	 */
	if (net_buf_frags_len(buf) == 0 ||
	    (buf == seg && net_buf_frags_len(buf) == len)) {
	if (buf->len == 0 || (buf == seg && buf->len == len)) {
		cb = l2cap_chan_sdu_sent;
	} else {
		cb = l2cap_chan_seg_sent;
@@ -2000,28 +1999,16 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch,

/* return next netbuf fragment if present, also assign metadata */
static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
				  struct net_buf **buf)
				  struct net_buf *buf)
{
	int ret;
	size_t sent, rem_len, frag_len;
	struct net_buf *frag;

	frag = *buf;
	if (!frag->len && frag->frags) {
		frag = frag->frags;
	}

	rem_len = net_buf_frags_len(frag);
	sent = 0;
	while (frag && sent != rem_len) {
		LOG_DBG("send frag %p (orig buf %p)", frag, *buf);
	size_t sent = 0;
	size_t rem_len = buf->len;

		frag_len = frag->len;
		ret = l2cap_chan_le_send(ch, frag, 0);
	while (buf && sent != rem_len) {
		ret = l2cap_chan_le_send(ch, buf, 0);
		if (ret < 0) {
			*buf = frag;

			LOG_DBG("failed to send frag (ch %p cid 0x%04x sent %d)",
			LOG_DBG("failed to send buf (ch %p cid 0x%04x sent %d)",
				ch, ch->tx.cid, sent);

			return ret;
@@ -2029,11 +2016,9 @@ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,

		sent += ret;

		/* If the current buffer has been fully consumed, destroy it and
		 * proceed to the next fragment of the netbuf chain.
		 */
		if (ret == frag_len) {
			frag = net_buf_frag_del(NULL, frag);
		/* If the current buffer has been fully consumed, destroy it */
		if (ret == rem_len) {
			net_buf_unref(buf);
		}
	}

@@ -2398,7 +2383,7 @@ static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
{
	int err;

	LOG_DBG("chan %p len %zu", chan, net_buf_frags_len(buf));
	LOG_DBG("chan %p len %zu", chan, buf->len);

	__ASSERT_NO_MSG(bt_l2cap_chan_get_state(&chan->chan) == BT_L2CAP_CONNECTED);
	__ASSERT_NO_MSG(atomic_get(&chan->rx.credits) == 0);
@@ -2425,7 +2410,7 @@ static void l2cap_chan_le_recv_seg(struct bt_l2cap_le_chan *chan,
	uint16_t len;
	uint16_t seg = 0U;

	len = net_buf_frags_len(chan->_sdu);
	len = chan->_sdu->len;
	if (len) {
		memcpy(&seg, net_buf_user_data(chan->_sdu), sizeof(seg));
	}
@@ -2440,7 +2425,7 @@ static void l2cap_chan_le_recv_seg(struct bt_l2cap_le_chan *chan,
	/* Store received segments in user_data */
	memcpy(net_buf_user_data(chan->_sdu), &seg, sizeof(seg));

	LOG_DBG("chan %p seg %d len %zu", chan, seg, net_buf_frags_len(buf));
	LOG_DBG("chan %p seg %d len %zu", chan, seg, buf->len);

	/* Append received segment to SDU */
	len = net_buf_append_bytes(chan->_sdu, buf->len, buf->data, K_NO_WAIT,
@@ -2451,7 +2436,7 @@ static void l2cap_chan_le_recv_seg(struct bt_l2cap_le_chan *chan,
		return;
	}

	if (net_buf_frags_len(chan->_sdu) < chan->_sdu_len) {
	if (chan->_sdu->len < chan->_sdu_len) {
		/* Give more credits if remote has run out of them, this
		 * should only happen if the remote cannot fully utilize the
		 * MPS for some reason.
@@ -3054,10 +3039,13 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)

static int bt_l2cap_dyn_chan_send(struct bt_l2cap_le_chan *le_chan, struct net_buf *buf)
{
	uint16_t sdu_len = net_buf_frags_len(buf);
	uint16_t sdu_len = buf->len;

	LOG_DBG("chan %p buf %p", le_chan, buf);

	/* Frags are not supported. */
	__ASSERT_NO_MSG(buf->frags == NULL);

	if (sdu_len > le_chan->tx.mtu) {
		LOG_ERR("attempt to send %u bytes on %u MTU chan",
			sdu_len, le_chan->tx.mtu);
@@ -3108,7 +3096,7 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
		return -EINVAL;
	}

	LOG_DBG("chan %p buf %p len %zu", chan, buf, net_buf_frags_len(buf));
	LOG_DBG("chan %p buf %p len %zu", chan, buf, buf->len);

	if (!chan->conn || chan->conn->state != BT_CONN_CONNECTED) {
		return -ENOTCONN;
+0 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ app=tests/bsim/bluetooth/host/l2cap/credits compile
app=tests/bsim/bluetooth/host/l2cap/credits conf_file=prj_ecred.conf compile
app=tests/bsim/bluetooth/host/l2cap/credits_seg_recv compile
app=tests/bsim/bluetooth/host/l2cap/credits_seg_recv conf_file=prj_ecred.conf compile
app=tests/bsim/bluetooth/host/l2cap/frags compile
app=tests/bsim/bluetooth/host/l2cap/send_on_connect compile
app=tests/bsim/bluetooth/host/l2cap/send_on_connect conf_file=prj_ecred.conf compile

+0 −16
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(bsim_test_l2cap_frags)

target_sources(app PRIVATE
  src/main.c
  src/common.c)

zephyr_include_directories(
  src/
  ${BSIM_COMPONENTS_PATH}/libUtilv1/src/
  ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
  )
+0 −22
Original line number Diff line number Diff line
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="L2CAP frags test"

CONFIG_BT_EATT=n
CONFIG_BT_L2CAP_ECRED=n

CONFIG_BT_SMP=y # Next config depends on it
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y

# Disable auto-initiated procedures so they don't
# mess with the test's execution.
CONFIG_BT_AUTO_PHY_UPDATE=n
CONFIG_BT_AUTO_DATA_LEN_UPDATE=n
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n

CONFIG_LOG=y
CONFIG_ASSERT=y

CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y
CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y
Loading