This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

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)
    {
        case NRF_BLE_GATT_EVT_ATT_MTU_UPDATED:
        {
            m_mtu_exchanged = true;
            NRF_LOG_INFO("ATT MTU exchange completed. MTU set to %u bytes.",
                         p_evt->params.att_mtu_effective);
        } break;

        case NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED:
        {
            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

  • #define DATA_LEN_MAX 251

    i run APP_ERROR_CHECK on nrf_ble_gatt_data_length_set and it never complains. I'm assuming this means no errors. 

  • Hmm, that is weird. Do you see the data length increasing if you set to a value below NRF_SDH_BLE_GATT_MAX_MTU_SIZE, i.e. 140? If not could you capture a sniffer trace with a BLE protocol analyzer or the nRF Sniffer? It would help to see if a request to increase the data length is sent or not. 

  • No, the data length does not increase when I set DATA_LEN_MAX to 130. Data length stays at 27. 

    I am using microBits as sniffers but they do not pick up my connection, so I don't have a sniffer trace to show. 

  • Actually, I just did a manual check and it reports that my data length is 140! I never get the NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED event, but it looks like the data length changed anyway!  I'm going to test it now. 

    void data_len_set(uint8_t value)
    {
        ret_code_t err_code;
        err_code = nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, value);
        APP_ERROR_CHECK(err_code);
    
        uint8_t future_data_length = 0;
        nrf_ble_gatt_data_length_get(&m_gatt, BLE_CONN_HANDLE_INVALID, &future_data_length);
        NRF_LOG_INFO("Next data length set to %u bytes.", future_data_length);
    }
    
    /**@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)
    {
        (void) p_gatt; //UNUSED 
    
        switch (p_evt->evt_id)
        {
            case NRF_BLE_GATT_EVT_ATT_MTU_UPDATED:
            {
    
                NRF_LOG_INFO("ATT MTU exchange completed. MTU set to %u bytes.",
                             p_evt->params.att_mtu_effective);
    
                NRF_LOG_INFO("Data length is %u bytes.", p_evt->params.data_length);
            } break;
    
            case NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED:
            {
                NRF_LOG_INFO("Data length updated to %u bytes.", p_evt->params.data_length);
            } break;
        }
    }

    <info> app: Next data length set to 144 bytes.
    <info> app: Slow advertising.
    <info> app: Connected to a previously bonded device.
    <debug> ble_gatt: Requesting to update ATT MTU to 140 bytes on connection 0x0.
    <debug> ble_gatt: Requesting to update data length to 144 on connection 0x0.
    <info> app: Reset challenge status on conn_handle 0x0
    <info> app: Connected
    <info> app: connection interval: min 24, max: 24
    <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.
    <info> app: Data length is 140 bytes.
    <info> app: Peer data updated.
    <info> app: Peer data updated.

    These results confuse me. It says "Requesting to update data length to 144", then it says "data length updated to 27 bytes". The number 27 is nowhere in my code. THEN it says "Data length IS 140". I'm just going to assume the data length is 140 now. Time to test. 

  • I think the data length is set to 27 before the ATT MTU update to 140 and then this update leads to the datalength being increased to  140. Let me know if you see 140byte on the air or not. 

Related