Skip to content

Network data usage of Azure IoT SDK over MQTT on idle connection.

ewertons edited this page May 8, 2020 · 2 revisions

Last edited on May 8th, 2020.

Run ont a Ubuntu 18.04 environment.

  1. Install Wireshark.
user@ubuntu:/$ sudo apt-get update
user@ubuntu:/$ sudo apt-get install wireshark
user@ubuntu:/$ sudo usermod -aG wireshark $(whoami)
user@ubuntu:/$ sudo reboot
  1. Clone, update samples and build the C SDK
user@ubuntu:/$ git clone --recursive https://github.com/azure/azure-iot-sdk-c.git 
user@ubuntu:/$ cd azure-iot-sdk-c

Update the sample 'iothub_ll_telemetry_sample.c' with your connection string (example below):

user@ubuntu:/azure-iot-sdk-c$ git diff
diff --git a/iothub_client/samples/iothub_ll_telemetry_sample/iothub_ll_telemetry_sample.c b/iothub_client/samples/iothub_ll_telemetry_sample/iothub_ll_telemetry_sample.c
index eb008853f..f62f2bdaf 100644
--- a/iothub_client/samples/iothub_ll_telemetry_sample/iothub_ll_telemetry_sample.c
+++ b/iothub_client/samples/iothub_ll_telemetry_sample/iothub_ll_telemetry_sample.c
@@ -50,7 +50,7 @@ and removing calls to _DoWork will yield the same results. */
 
 
 /* Paste in the your iothub connection string  */
-static const char* connectionString = "[device connection string]";
+static const char* connectionString = "HostName=REDACTED.azure-devices.net;DeviceId=deviceid;SharedAccessKey=READACTED";
 #define MESSAGE_COUNT        5
 static bool g_continueRunning = true;
 static size_t g_message_count_send_confirmations = 0;
@@ -170,7 +170,7 @@ int main(void)
             else if (g_message_count_send_confirmations >= MESSAGE_COUNT)
             {
                 // After all messages are all received stop running
-                g_continueRunning = false;
+                // g_continueRunning = false;
             }
 
             IoTHubDeviceClient_LL_DoWork(device_ll_handle);
user@ubuntu:/azure-iot-sdk-c$

Continue with building:

user@ubuntu:/azure-iot-sdk-c$ mkdir cmake
user@ubuntu:/azure-iot-sdk-c$ cd cmake
user@ubuntu:/azure-iot-sdk-c/cmake$ cmake -DCMAKE_BUILD_TYPE=Debug ..
user@ubuntu:/azure-iot-sdk-c/cmake$ make -j
  1. Find your IoT Hub ip address
user@ubuntu:~$ nslookup REDACTED.azure-devices.net
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
REDACTED.azure-devices.net	canonical name = ihsu-prod-xyz-000.cloudapp.net.
Name:	ihsu-prod-xyz-000.cloudapp.net
Address: 111.222.333.444

user@ubuntu:~$
  1. Open Wireshark on desktop UI.

  2. Select the interface to capture on.

  3. Apply a filter to show only traffic to/from the Azure IoT Hub

ip.addr == 111.222.333.444

  1. Click to start capturing.

  2. Run the sample

user@ubuntu:/azure-iot-sdk-c/cmake$ cd iothub_client/samples/iothub_ll_telemetry_sample/
user@ubuntu:/azure-iot-sdk-c/cmake/iothub_client/samples/iothub_ll_telemetry_sample/$ ./iothub_ll_telemetry_sample 
Creating IoTHub Device handle
Sending message 1 to IoTHub
Sending message 2 to IoTHub
Sending message 3 to IoTHub
Sending message 4 to IoTHub
Sending message 5 to IoTHub
-> 14:48:15 CONNECT | VER: 4 | KEEPALIVE: 240 | FLAGS: 192 | USERNAME: REDACTED.azure-devices.net/deviceid/?api-version=2017-11-08-preview&DeviceClientType=iothubclient%2f1.3.8%20(native%3b%20Linux%3b%20x86_64) | PWD: XXXX | CLEAN: 0
<- 14:48:15 CONNACK | SESSION_PRESENT: true | RETURN_CODE: 0x0
The device client is connected to iothub
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 2 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 3 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 4 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 5 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 6 | PAYLOAD_LEN: 12
<- 14:48:15 PUBACK | PACKET_ID: 2
Confirmation callback received for message 1 with result IOTHUB_CLIENT_CONFIRMATION_OK
<- 14:48:15 PUBACK | PACKET_ID: 3
Confirmation callback received for message 2 with result IOTHUB_CLIENT_CONFIRMATION_OK
<- 14:48:15 PUBACK | PACKET_ID: 4
Confirmation callback received for message 3 with result IOTHUB_CLIENT_CONFIRMATION_OK
<- 14:48:15 PUBACK | PACKET_ID: 5
Confirmation callback received for message 4 with result IOTHUB_CLIENT_CONFIRMATION_OK
<- 14:48:15 PUBACK | PACKET_ID: 6
Confirmation callback received for message 5 with result IOTHUB_CLIENT_CONFIRMATION_OK
-> 14:52:15 PINGREQ
<- 14:52:15 PINGRESP
  1. Collect the traces from Wireshark
"No.","Time","Source","Destination","Protocol","Length","Info"
"5","2.180387533","192.168.1.186","111.222.333.444","TCP","74","38328  >  8883 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=202858383 TSecr=0 WS=128"
"6","2.225055787","111.222.333.444","192.168.1.186","TCP","74","8883  >  38328 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1440 WS=256 SACK_PERM=1 TSval=433712819 TSecr=202858383"
"7","2.225144862","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1 Ack=1 Win=64256 Len=0 TSval=202858428 TSecr=433712819"
"8","2.225557512","192.168.1.186","111.222.333.444","TLSv1.2","359","Client Hello"
"9","2.277717873","111.222.333.444","192.168.1.186","TLSv1.2","4083","Server Hello, Certificate, Server Key Exchange, Certificate Request, Server Hello Done"
"10","2.277766831","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=294 Ack=4018 Win=62720 Len=0 TSval=202858481 TSecr=433712866"
"11","2.288469964","192.168.1.186","111.222.333.444","TLSv1.2","276","Certificate, Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message"
"12","2.335115283","111.222.333.444","192.168.1.186","TLSv1.2","157","Change Cipher Spec, Encrypted Handshake Message"
"13","2.335169316","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=504 Ack=4109 Win=64128 Len=0 TSval=202858538 TSecr=433712928"
"14","2.335660797","192.168.1.186","111.222.333.444","TLSv1.2","487","Application Data"
"15","2.387524386","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"16","2.387602485","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=925 Ack=4178 Win=64128 Len=0 TSval=202858591 TSecr=433712981"
"17","2.390251353","192.168.1.186","111.222.333.444","TLSv1.2","215","Application Data"
"18","2.465242544","111.222.333.444","192.168.1.186","TCP","66","8883  >  38328 [ACK] Seq=4178 Ack=1074 Win=262656 Len=0 TSval=433713059 TSecr=202858593"
"19","2.465305781","192.168.1.186","111.222.333.444","TLSv1.2","662","Application Data, Application Data, Application Data, Application Data"
"20","2.514491256","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"21","2.529349441","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"22","2.529551485","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1670 Ack=4316 Win=64128 Len=0 TSval=202858733 TSecr=433713106"
"23","2.547088383","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"24","2.572525823","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"25","2.572676666","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1670 Ack=4454 Win=64128 Len=0 TSval=202858776 TSecr=433713138"
"26","2.588395105","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"27","2.630312977","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1670 Ack=4523 Win=64128 Len=0 TSval=202858833 TSecr=433713174"
"169","242.390700741","192.168.1.186","111.222.333.444","TLSv1.2","135","Application Data"
"170","242.436047043","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"
"171","242.436115051","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1739 Ack=4592 Win=64128 Len=0 TSval=203098639 TSecr=433953094"
  1. Traffic analysis:
"No.","Time","Source","Destination","Protocol","Length","Info"
"5","2.180387533","192.168.1.186","111.222.333.444","TCP","74","38328  >  8883 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=202858383 TSecr=0 WS=128"
"6","2.225055787","111.222.333.444","192.168.1.186","TCP","74","8883  >  38328 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1440 WS=256 SACK_PERM=1 TSval=433712819 TSecr=202858383"
"7","2.225144862","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1 Ack=1 Win=64256 Len=0 TSval=202858428 TSecr=433712819"
"8","2.225557512","192.168.1.186","111.222.333.444","TLSv1.2","359","Client Hello"
"9","2.277717873","111.222.333.444","192.168.1.186","TLSv1.2","4083","Server Hello, Certificate, Server Key Exchange, Certificate Request, Server Hello Done"
"10","2.277766831","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=294 Ack=4018 Win=62720 Len=0 TSval=202858481 TSecr=433712866"
"11","2.288469964","192.168.1.186","111.222.333.444","TLSv1.2","276","Certificate, Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message"
"12","2.335115283","111.222.333.444","192.168.1.186","TLSv1.2","157","Change Cipher Spec, Encrypted Handshake Message"
"13","2.335169316","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=504 Ack=4109 Win=64128 Len=0 TSval=202858538 TSecr=433712928"
"14","2.335660797","192.168.1.186","111.222.333.444","TLSv1.2","487","Application Data"

-> 14:48:15 CONNECT | VER: 4 | KEEPALIVE: 240 | FLAGS: 192 | USERNAME: REDACTED.azure-devices.net/deviceid/?api-version=2017-11-08-preview&DeviceClientType=iothubclient%2f1.3.8%20(native%3b%20Linux%3b%20x86_64) | PWD: XXXX | CLEAN: 0

"15","2.387524386","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:48:15 CONNACK | SESSION_PRESENT: true | RETURN_CODE: 0x0

"16","2.387602485","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=925 Ack=4178 Win=64128 Len=0 TSval=202858591 TSecr=433712981"
"17","2.390251353","192.168.1.186","111.222.333.444","TLSv1.2","215","Application Data"

-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 2 | PAYLOAD_LEN: 12

"18","2.465242544","111.222.333.444","192.168.1.186","TCP","66","8883  >  38328 [ACK] Seq=4178 Ack=1074 Win=262656 Len=0 TSval=433713059 TSecr=202858593"
"19","2.465305781","192.168.1.186","111.222.333.444","TLSv1.2","662","Application Data, Application Data, Application Data, Application Data"

-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 3 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 4 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 5 | PAYLOAD_LEN: 12
-> 14:48:15 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/deviceid/messages/events/property_key=property_value | PACKET_ID: 6 | PAYLOAD_LEN: 12

"20","2.514491256","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:48:15 PUBACK | PACKET_ID: 2

"21","2.529349441","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:48:15 PUBACK | PACKET_ID: 3

"22","2.529551485","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1670 Ack=4316 Win=64128 Len=0 TSval=202858733 TSecr=433713106"
"23","2.547088383","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:48:15 PUBACK | PACKET_ID: 4

"24","2.572525823","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:48:15 PUBACK | PACKET_ID: 5

"25","2.572676666","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1670 Ack=4454 Win=64128 Len=0 TSval=202858776 TSecr=433713138"
"26","2.588395105","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:48:15 PUBACK | PACKET_ID: 6

"27","2.630312977","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1670 Ack=4523 Win=64128 Len=0 TSval=202858833 TSecr=433713174"
"169","242.390700741","192.168.1.186","111.222.333.444","TLSv1.2","135","Application Data"

-> 14:52:15 PINGREQ

"170","242.436047043","111.222.333.444","192.168.1.186","TLSv1.2","135","Application Data"

<- 14:52:15 PINGRESP

"171","242.436115051","192.168.1.186","111.222.333.444","TCP","66","38328  >  8883 [ACK] Seq=1739 Ack=4592 Win=64128 Len=0 TSval=203098639 TSecr=433953094"

Traffic on wire:

Message Size (bytes)
CONNECT 487
CONNACK 135
PUBLISH (1 telemetry) 215
PUBLISH (4 telemetry) 662
PUBACK (telemetry) 135
PINGREQ 135
PINGRESP 135
DISCONNECT 135

Plus 66-byte TCP ACKs.

If no messages are actively sent or received by the user, the IoT Hub client uses data traffic to account for (MQTT) keep-alives and SAS token refreshes.

For simplification, the calculations below will ignore TCP ACK sizes.

Keep Alives

Keep-alives are exchanged every 4 minutes by default, what results in 4050 bytes/hour, or 97.2 Kbytes/day.

According to the offical documentation, the maximum keep alive frequency is one every 1767 seconds:

So if the MQTT timeout is changed in the IoT client to every 1760 seconds (for safety to avoid disconnection), the data usage for keep-alives would be 552.3 bytes/hour (a reduction of 86% of keep-alive data usage).

To change the MQTT keep-alive frequency, do:

uint16_t keepAlivePeriodInSecs = 1760;
IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_KEEP_ALIVE, &keepAlivePeriodInSecs);

SAS Token refresh

The second optimization that can be done is in the frequency of re-connections for SAS token refreshes.

By default the IoT client generates SAS tokens that are valid for 60 minutes, and "refreshes" them every 80% of that valid period (48 minutes).

Since with MQTT 3.1.1 there is no way to update credentials over the same connection, the IoT client disconnects and reconnects with a new SAS token.

A CONNECT packet is 487 bytes long, while a DISCONNECT is 135 bytes.

So every re-connection uses 622 bytes, and since there is one reconnect every 48 minutes, by default the IoT client uses on average 778 bytes/hour for SAS token refreshes.

Reducing the frequency of SAS token refreshes to once every 12 hours results in a traffic usage for re-connections of 65 bytes/hour, on average (a reduction of 91.7% of SAS token refresh data usage).

The SAS token expiration time can be changed using the following:

size_t sasTokenExpiryTimeInInSecs = 30;
IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_SAS_TOKEN_LIFETIME, &sasTokenExpiryTimeInInSecs);
  1. Summary

In summary, the default data usage of the IoT Hub client for SAS token refreshes and keep-alives is of about 4602.3 bytes/hour.

If optimizations are applied to reduce the keep-alives to once every 1760 seconds and SAS token refreshes to once every 12 hours, the data traffic is decreases to 617.3 bytes/hour (a reduction of 86.6%).