What is the difference between "data length" and MTU?

I want to use BLE 4.2 Data length extension to stuff more data into one packet. I am looking at the "ble_app_att_mtu_throughput" example and am getting confused because there is both a NRF_BLE_GATT_EVT_ATT_MTU_UPDATED event and a NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED event.

/**@brief Function for handling events from the GATT library. */
static void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    switch (p_evt->evt_id)
            m_mtu_exchanged = true;
            NRF_LOG_INFO("ATT MTU exchange completed. MTU set to %u bytes.",
        } break;

            m_data_length_updated = true;
            NRF_LOG_INFO("Data length updated to %u bytes.", p_evt->params.data_length);
        } break;

    nrf_ble_amts_on_gatt_evt(&m_amts, p_evt);

I thought "data length" = MTU - 3. If so, then why are there two event types, and why is there a voided function "nrf_ble_gatt_data_length_set" here? 

void data_len_ext_set(bool status)
    m_test_params.data_len_ext_enabled = status;

    uint8_t data_length = status ? (247 + L2CAP_HDR_LEN) : (23 + L2CAP_HDR_LEN);
    (void) nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, data_length);

Especially confusing is this line in amts.c, which suggests data length = MTU - 3

void nrf_ble_amts_on_gatt_evt(nrf_ble_amts_t * p_ctx, nrf_ble_gatt_evt_t const * p_gatt_evt)
    if (p_gatt_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
        p_ctx->max_payload_len =
            p_gatt_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;

My current project outputs this. MTU = 140. Does that mean I can assume my data length is 140 - 3  = 137? 

<debug> ble_gatt: Data length updated to 27 on connection 0x0.
<debug> ble_gatt: max_rx_octets: 27
<debug> ble_gatt: max_tx_octets: 27
<debug> ble_gatt: max_rx_time: 328
<debug> ble_gatt: max_tx_time: 328
<info> app: Data length updated to 27 bytes.
<info> app: Bonding...
<info> app: Connection secured: role: 1, conn_handle: 0x0, procedure: 0.
<debug> ble_gatt: ATT MTU updated to 140 bytes on connection 0x0 (response).
<info> app: ATT MTU exchange completed. MTU set to 140 bytes.

SDK 14.0.0

Softdevice S132 5.0.0

No Data
  • Hi Andrew, 

    the ATT MTU is the maximum transmission unit for the the ATT protocol which encapsulated inside the Data Channel PDU and the data length is the the size of the Data Channel PDU, see this illustration. 

    So if the ATT MTU is increased to 140, but the Data length is 27, then the ATT data will be segmented into 27byte chunks. Hence, if you want to fit the entire ATT MTU within the Data Channel PDU(i.e. one BLE data packet), then the Data length must be set higher than the ATT MTU size. 

    From the log output it still appers that the Data length is 27 bytes. 

    What have you set the following macros to in sdk_config?