linux/net
Frédéric Danis 042bb9603c Bluetooth: L2CAP: Fix L2CAP MTU negotiation
OBEX download from iPhone is currently slow due to small packet size
used to transfer data which doesn't follow the MTU negotiated during
L2CAP connection, i.e. 672 bytes instead of 32767:

  < ACL Data TX: Handle 11 flags 0x00 dlen 12
      L2CAP: Connection Request (0x02) ident 18 len 4
        PSM: 4103 (0x1007)
        Source CID: 72
  > ACL Data RX: Handle 11 flags 0x02 dlen 16
      L2CAP: Connection Response (0x03) ident 18 len 8
        Destination CID: 14608
        Source CID: 72
        Result: Connection successful (0x0000)
        Status: No further information available (0x0000)
  < ACL Data TX: Handle 11 flags 0x00 dlen 27
      L2CAP: Configure Request (0x04) ident 20 len 19
        Destination CID: 14608
        Flags: 0x0000
        Option: Maximum Transmission Unit (0x01) [mandatory]
          MTU: 32767
        Option: Retransmission and Flow Control (0x04) [mandatory]
          Mode: Enhanced Retransmission (0x03)
          TX window size: 63
          Max transmit: 3
          Retransmission timeout: 2000
          Monitor timeout: 12000
          Maximum PDU size: 1009
  > ACL Data RX: Handle 11 flags 0x02 dlen 26
      L2CAP: Configure Request (0x04) ident 72 len 18
        Destination CID: 72
        Flags: 0x0000
        Option: Retransmission and Flow Control (0x04) [mandatory]
          Mode: Enhanced Retransmission (0x03)
          TX window size: 32
          Max transmit: 255
          Retransmission timeout: 0
          Monitor timeout: 0
          Maximum PDU size: 65527
        Option: Frame Check Sequence (0x05) [mandatory]
          FCS: 16-bit FCS (0x01)
  < ACL Data TX: Handle 11 flags 0x00 dlen 29
      L2CAP: Configure Response (0x05) ident 72 len 21
        Source CID: 14608
        Flags: 0x0000
        Result: Success (0x0000)
        Option: Maximum Transmission Unit (0x01) [mandatory]
          MTU: 672
        Option: Retransmission and Flow Control (0x04) [mandatory]
          Mode: Enhanced Retransmission (0x03)
          TX window size: 32
          Max transmit: 255
          Retransmission timeout: 2000
          Monitor timeout: 12000
          Maximum PDU size: 1009
  > ACL Data RX: Handle 11 flags 0x02 dlen 32
      L2CAP: Configure Response (0x05) ident 20 len 24
        Source CID: 72
        Flags: 0x0000
        Result: Success (0x0000)
        Option: Maximum Transmission Unit (0x01) [mandatory]
          MTU: 32767
        Option: Retransmission and Flow Control (0x04) [mandatory]
          Mode: Enhanced Retransmission (0x03)
          TX window size: 63
          Max transmit: 3
          Retransmission timeout: 2000
          Monitor timeout: 12000
          Maximum PDU size: 1009
        Option: Frame Check Sequence (0x05) [mandatory]
          FCS: 16-bit FCS (0x01)
  ...
  > ACL Data RX: Handle 11 flags 0x02 dlen 680
      Channel: 72 len 676 ctrl 0x0202 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
      I-frame: Unsegmented TxSeq 1 ReqSeq 2
  < ACL Data TX: Handle 11 flags 0x00 dlen 13
      Channel: 14608 len 9 ctrl 0x0204 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
      I-frame: Unsegmented TxSeq 2 ReqSeq 2
  > ACL Data RX: Handle 11 flags 0x02 dlen 680
      Channel: 72 len 676 ctrl 0x0304 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
      I-frame: Unsegmented TxSeq 2 ReqSeq 3

The MTUs are negotiated for each direction. In this traces 32767 for
iPhone->localhost and no MTU for localhost->iPhone, which based on
'4.4 L2CAP_CONFIGURATION_REQ' (Core specification v5.4, Vol. 3, Part
A):

  The only parameters that should be included in the
  L2CAP_CONFIGURATION_REQ packet are those that require different
  values than the default or previously agreed values.
  ...
  Any missing configuration parameters are assumed to have their
  most recently explicitly or implicitly accepted values.

and '5.1 Maximum transmission unit (MTU)':

  If the remote device sends a positive L2CAP_CONFIGURATION_RSP
  packet it should include the actual MTU to be used on this channel
  for traffic flowing into the local device.
  ...
  The default value is 672 octets.

is set by BlueZ to 672 bytes.

It seems that the iPhone used the lowest negotiated value to transfer
data to the localhost instead of the negotiated one for the incoming
direction.

This could be fixed by using the MTU negotiated for the other
direction, if exists, in the L2CAP_CONFIGURATION_RSP.
This allows to use segmented packets as in the following traces:

  < ACL Data TX: Handle 11 flags 0x00 dlen 12
        L2CAP: Connection Request (0x02) ident 22 len 4
          PSM: 4103 (0x1007)
          Source CID: 72
  < ACL Data TX: Handle 11 flags 0x00 dlen 27
        L2CAP: Configure Request (0x04) ident 24 len 19
          Destination CID: 2832
          Flags: 0x0000
          Option: Maximum Transmission Unit (0x01) [mandatory]
            MTU: 32767
          Option: Retransmission and Flow Control (0x04) [mandatory]
            Mode: Enhanced Retransmission (0x03)
            TX window size: 63
            Max transmit: 3
            Retransmission timeout: 2000
            Monitor timeout: 12000
            Maximum PDU size: 1009
  > ACL Data RX: Handle 11 flags 0x02 dlen 26
        L2CAP: Configure Request (0x04) ident 15 len 18
          Destination CID: 72
          Flags: 0x0000
          Option: Retransmission and Flow Control (0x04) [mandatory]
            Mode: Enhanced Retransmission (0x03)
            TX window size: 32
            Max transmit: 255
            Retransmission timeout: 0
            Monitor timeout: 0
            Maximum PDU size: 65527
          Option: Frame Check Sequence (0x05) [mandatory]
            FCS: 16-bit FCS (0x01)
  < ACL Data TX: Handle 11 flags 0x00 dlen 29
        L2CAP: Configure Response (0x05) ident 15 len 21
          Source CID: 2832
          Flags: 0x0000
          Result: Success (0x0000)
          Option: Maximum Transmission Unit (0x01) [mandatory]
            MTU: 32767
          Option: Retransmission and Flow Control (0x04) [mandatory]
            Mode: Enhanced Retransmission (0x03)
            TX window size: 32
            Max transmit: 255
            Retransmission timeout: 2000
            Monitor timeout: 12000
            Maximum PDU size: 1009
  > ACL Data RX: Handle 11 flags 0x02 dlen 32
        L2CAP: Configure Response (0x05) ident 24 len 24
          Source CID: 72
          Flags: 0x0000
          Result: Success (0x0000)
          Option: Maximum Transmission Unit (0x01) [mandatory]
            MTU: 32767
          Option: Retransmission and Flow Control (0x04) [mandatory]
            Mode: Enhanced Retransmission (0x03)
            TX window size: 63
            Max transmit: 3
            Retransmission timeout: 2000
            Monitor timeout: 12000
            Maximum PDU size: 1009
          Option: Frame Check Sequence (0x05) [mandatory]
            FCS: 16-bit FCS (0x01)
  ...
  > ACL Data RX: Handle 11 flags 0x02 dlen 1009
        Channel: 72 len 1005 ctrl 0x4202 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
        I-frame: Start (len 21884) TxSeq 1 ReqSeq 2
  > ACL Data RX: Handle 11 flags 0x02 dlen 1009
        Channel: 72 len 1005 ctrl 0xc204 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
        I-frame: Continuation TxSeq 2 ReqSeq 2

This has been tested with kernel 5.4 and BlueZ 5.77.

Cc: stable@vger.kernel.org
Signed-off-by: Frédéric Danis <frederic.danis@collabora.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-06-20 11:54:48 -04:00
..
6lowpan
9p netfs: Fix the request's work item to not require a ref 2025-05-21 14:35:20 +02:00
802 treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
8021q net: 802: Remove unused p8022 code 2025-04-22 07:04:02 -07:00
appletalk treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
atm net: atm: fix /proc/net/atm/lec handling 2025-06-19 08:36:31 -07:00
ax25 treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
batman-adv treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
bluetooth Bluetooth: L2CAP: Fix L2CAP MTU negotiation 2025-06-20 11:54:48 -04:00
bpf selftests/bpf: Add test to access const void pointer argument in tracing program 2025-04-23 11:26:22 -07:00
bridge treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
caif rtnetlink: Pack newlink() params into struct 2025-02-21 15:28:02 -08:00
can treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
ceph A small CephFS encryption-related fix and a dead code cleanup. 2025-04-25 15:51:28 -07:00
core net: netmem: fix skb_ensure_writable with unreadable skbs 2025-06-17 15:48:20 -07:00
dcb
devlink devlink: use DEVLINK_VAR_ATTR_TYPE_* instead of NLA_* in fmsg 2025-05-06 18:21:11 -07:00
dns_resolver
dsa net: dsa: tag_brcm: legacy: fix pskb_may_pull length 2025-05-30 19:20:18 -07:00
ethernet
ethtool Including fixes from bluetooth and wireless. 2025-06-12 09:50:36 -07:00
handshake
hsr treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
ieee802154 treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
ife
ipv4 tcp: fix passive TFO socket having invalid NAPI ID 2025-06-18 18:30:51 -07:00
ipv6 calipso: Fix null-ptr-deref in calipso_req_{set,del}attr(). 2025-06-19 08:33:09 -07:00
iucv s390: Convert MACHINE_IS_[LPAR|VM|KVM], etc, machine_is_[lpar|vm|kvm]() 2025-03-04 17:18:07 +01:00
kcm
key xfrm: Migrate offload configuration 2025-04-17 11:00:03 +02:00
l2tp net: move misc netdev_lock flavors to a separate header 2025-03-08 09:06:50 -08:00
l3mdev net: fib_rules: Fix iif / oif matching on L3 master device 2025-04-15 17:54:56 -07:00
lapb treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
llc treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
mac80211 wifi: mac80211: don't WARN for late channel/color switch 2025-06-17 14:30:06 +02:00
mac802154 mac802154: Switch to use hrtimer_setup() 2025-02-18 10:35:44 +01:00
mctp net: mctp: use nlmsg_payload() for netlink message data extraction 2025-05-26 17:38:27 +02:00
mpls mpls: Use rcu_dereference_rtnl() in mpls_route_input_rcu(). 2025-06-17 18:21:59 -07:00
mptcp treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
ncsi treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
netfilter treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
netlabel calipso: unlock rcu before returning -EAFNOSUPPORT 2025-06-05 08:03:38 -07:00
netlink netlink: fix policy dump for int with validation callback 2025-05-12 18:50:09 -07:00
netrom treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
nfc NFC: nci: uart: Set tty->disc_data only in success path 2025-06-19 08:33:54 -07:00
nsh
openvswitch openvswitch: Allocate struct ovs_pcpu_storage dynamically 2025-06-17 14:47:46 +02:00
packet treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
phonet
psample
qrtr
rds replace strncpy with strscpy_pad 2025-05-26 22:28:44 +02:00
rfkill net: rfkill: gpio: allow booting in blocked state 2025-02-11 11:55:55 +01:00
rose treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
rxrpc treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
sched net/sched: fix use-after-free in taprio_dev_notifier 2025-06-17 16:14:04 -07:00
sctp treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
shaper
smc smc: Fix lockdep false-positive for IPPROTO_SMC. 2025-04-11 14:14:26 -07:00
strparser strparser: Remove unused __strp_unpause 2025-05-05 16:48:12 -07:00
sunrpc treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
switchdev net: switchdev: Convert blocking notification chain to a raw one 2025-03-11 11:30:28 +01:00
tipc tipc: fix null-ptr-deref when acquiring remote ip of ethernet bearer 2025-06-18 14:19:50 -07:00
tls bpf-next-6.16 2025-05-28 15:52:42 -07:00
unix af_unix: Allow passing cred for embryo without SO_PASSCRED/SO_PASSPIDFD. 2025-06-12 08:13:06 -07:00
vmw_vsock Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-05-28 10:11:15 +02:00
wireless Including fixes from bluetooth and wireless. 2025-06-12 09:50:36 -07:00
x25 treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
xdp Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-05-22 09:42:41 -07:00
xfrm treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
compat.c
devres.c
Kconfig net: Kconfig NET_DEVMEM selects GENERIC_ALLOCATOR 2025-05-27 17:31:42 -07:00
Kconfig.debug
Makefile net: Retire DCCP socket. 2025-04-11 18:58:10 -07:00
socket.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-03-26 09:32:10 -07:00
sysctl_net.c