Paper · 2019-06-22 · cs.RO, cs.NI
Micro Air Vehicle Link (MAVLink) in a Nutshell: A Survey
Survey and tutorial of MAVLink, the binary message protocol between drones and ground stations. Gives the MAVLink 1.0 and 2.0 frame layouts, key messages and commands, flight modes, the protocol's security gaps and proposed fixes (encryption, MAC, packet signing, intrusion detection), and surveyed research and software. It reports no new experiments.
Intrusion detectionMessage authentication code (MAC)Cyclic redundancy check (CRC)uavcommunication-protocoltelemetrysecuritysurveymavlink
AI-compiled by claude-haiku-5-5 on 2026-11-06, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.
In plain words
Drones and their ground stations need a shared language so that a laptop can ask a drone for its position, or tell it to land. MAVLink is that language. It packs each message into a short block of bytes with a small header, so it works over slow radio links as well as over Wi-Fi. This paper is a guided tour of the language: how a message is laid out, which messages matter most, how the drone flight modes are used in practice, and what an attacker can do when the language has no encryption and no sender check. It also lists the research that has tried to fix these gaps and the software tools that speak it. The paper is a survey, so it runs no experiments of its own.
TL;DR
- A survey and tutorial of the MAVLink 1.0 and 2.0 binary protocol, with frame layouts, key messages, commands and flight modes §II.
- The paper's threat list says MAVLink has no native encryption and only weak authentication; MAVLink 2 adds optional packet signing §III.B §II.C.2.
- Reports no new results. Its value is the reference material, the list of attacks, and the list of proposed fixes.
- Not endorsed by the authors. Section numbers below follow the paper's Roman numerals (for example §II.C.1 is Section II, subsection C, sub-subsection 1).
Problem
Ground stations and autopilots exchanged messages without a shared reference, and the authors found no structured survey or tutorial of the protocol §I. The paper's aim is to be that reference, covering both versions, the main messages, the tools, and the security literature §I §VII.
Method
This paper has no method of its own. Its content is a description of the MAVLink protocol and a classification of prior work. The sections below summarise the parts an implementer needs.
Transport. MAVLink messages are binary-serialised and carried over a serial telemetry link, Wi-Fi, or Ethernet. Telemetry radios at 433, 868 or 915 MHz are described with a maximum data rate of 250 kbps and a typical range of 500 m, environment-dependent §II.B. Over IP, the paper says UDP is connectionless and fast but unreliable, and TCP is reliable but can congest; the choice is left to the user §II.B tab. I.
MAVLink 1.0 frame. A frame has eight fields: a start byte (0xFE), payload length (LEN), sequence number (SEQ, 0 to 255, wraps around and detects losses), system ID (SYS, 1 to 255; 255 is the usual ground-station ID), component ID (COMP), message ID (MSG, one byte), payload (up to 255 bytes), and a two-byte checksum (CKA, CKB) §II.C.1 tab. II fig. 1. The minimum frame is 8 bytes and the maximum is 263 bytes §II.C.1.
MAVLink 2.0 frame. The start byte is 0xFD. Two flag bytes come after the length: incompatibility flags, where 0x01 means the frame is signed, and compatibility flags, which a parser may ignore. SEQ, SYS and COMP keep their meaning. The message ID grows to 24 bits, and the payload is still at most 255 bytes. The checksum works as in 1.0. A signed frame carries a 13-byte block after the checksum §II.C.2 fig. 2.
Signature block (13 bytes). LinkID (1 byte, one per channel), timestamp (6 bytes, in 10-microsecond units since 1 January 2015 GMT, increasing per message on a stream), and signature (6 bytes). The stream is keyed by the tuple (SystemID, ComponentID, LinkID). The signature is the first 6 bytes of a SHA-256 value computed over the message and timestamp with a 32-byte shared secret key §II.C.2. A signed frame is dropped if its timestamp is older than the last one on its stream, if the signature does not match, or if the timestamp is more than one minute from the local clock. Unsigned frames are accepted or rejected as the implementation chooses §II.C.2.
Messages. Messages are split into state messages (drone to ground) and command messages (ground to drone) §II.D. IDs below 255 are shared by 1.0 and 2.0 §II.D. The most used ones the paper describes:
- HEARTBEAT (ID 0), sent about once a second, carries vehicle type, autopilot type, a base-mode bit field, a custom mode and a system status §II.D.1 fig. 3. Type values named include 1 (fixed wing), 2 (quadrotor) and 4 (helicopter); autopilot values include 0 (generic), 3 (ArduPilot) and 12 (PX4) §II.D.1.
- SYS_STATUS (ID 1) reports onboard sensor state, battery and link quality §II.D.1 tab. IV.
- GLOBAL_POSITION_INT (ID 33) reports latitude and longitude, each to be divided by 10^7 for degrees, and altitude in millimetres; it also carries a relative altitude to the take-off point and the velocity components §II.D.1 fig. 4.
- COMMAND_LONG (ID 76) has 11 fields: target system, target component, command ID, a confirmation counter (0 on the first send), and seven parameters §II.D.2 tab. III fig. 5. Examples: LAND (21, no parameters), TAKEOFF (22, altitude in parameter 7 per the text), ARM/DISARM (400, boolean in parameter 1) tab. III.
- MISSION_ITEM (ID 39) sends one waypoint. The sequence number starts at 0, which the paper says is the home location. The coordinate frame, for example global or global-relative-altitude, decides how the three coordinates are read §II.D.2.
Flight modes (ArduPilot). STABILIZE gives full manual control; ALT_HOLD holds altitude with a PID loop using the barometer and leaves heading and position to the pilot; LOITER holds position, heading and altitude once the sticks are released and needs a 3D GPS fix; LAND and RTL land or return to the take-off point; GUIDED flies to a single GPS waypoint; AUTO follows a stored mission §II.E. The paper gives 500 cm/s as the typical LOITER speed, and the default maximum acceleration as half of that speed §II.E.
Parsing sketch. The paper gives no code. The sketch below is ours; it follows the field layout above and marks every point the paper leaves open.
# Split one MAVLink frame into fields [§II.C.1] [§II.C.2] [tab. II]
# Input: buffer (bytes) starting at a candidate frame
# Output: dict of fields, or None if the start byte is unknown
def parse_frame(buffer):
# Pick the layout from the start-of-frame byte [§II.C.1] [§II.C.2]
if buffer[0] == 0xFE:
version = 1
header_size = 6 # STX, LEN, SEQ, SYS, COMP, MSG
elif buffer[0] == 0xFD:
version = 2
header_size = 10 # STX, LEN, INC, CMP, SEQ, SYS, COMP, MSGID x3
else:
return None
# Payload length is the second byte in both versions [§II.C.1]
payload_length = buffer[1]
payload_end = header_size + payload_length
# Payload is at most 255 bytes [§II.C.1] [§II.C.2]
checksum = buffer[payload_end:payload_end + 2] # CKA, CKB
# Message ID: 1 byte in v1, 3 bytes in v2 [§II.C.1] [§II.C.2]
if version == 1:
msg_id = buffer[5]
else:
# Byte order of the 3-byte ID is not stated in the paper
msg_id = read_uint24(buffer[7:10])
# Checksum: X.25 CRC over all bytes after STX, then a per-message
# seed [§II.C.1]. The seed table is not in the paper.
crc_input = buffer[1:payload_end] + bytes([crc_extra(msg_id)])
# How CKA and CKB map onto the 16-bit CRC is not stated
if crc_x25(crc_input) != checksum:
return None
# Signed v2 frames carry 13 more bytes after the checksum [§II.C.2]
signed = version == 2 and (buffer[2] & 0x01) == 0x01 # INC flag
return {
"version": version,
"msg_id": msg_id,
"payload": buffer[header_size:payload_end],
"signed": signed,
}Signature check for a signed v2 frame:
# Accept or reject one signed MAVLink 2 frame [§II.C.2]
# Input: frame (parsed), signature (13 bytes), key (32 bytes),
# last_seen (dict per stream), local_time (seconds)
# Output: True if accepted
def accept_signed_frame(frame, signature, key, last_seen, local_time):
# Signature block: LinkID (1), timestamp (6), tag (6) [§II.C.2]
link_id = signature[0]
timestamp = to_int(signature[1:7]) # 10 us units since 2015-01-01
tag = signature[7:13]
# Streams are keyed by (SystemID, ComponentID, LinkID) [§II.C.2]
stream = (frame.sys_id, frame.comp_id, link_id)
# Drop frames older than the last one seen on this stream [§II.C.2]
if timestamp < last_seen.get(stream, 0):
return False
# Drop frames more than one minute away from local time [§II.C.2]
if abs(local_time - timestamp_seconds(timestamp)) > 60:
return False
# Recompute the tag. Combining message, timestamp and key is not
# specified in the paper; combine() is a placeholder. [§II.C.2]
digest_input = combine(frame.bytes_unsigned, timestamp, key)
if first_six_bytes(sha256(digest_input)) != tag:
return False
# Remember the newest timestamp for this stream
last_seen[stream] = timestamp
return TrueHeartbeat base_mode bits, as the paper lists them §II.D.1:
# Read the HEARTBEAT base_mode bit field [§II.D.1]
# Input: base_mode (8-bit int)
# Output: dict of mode flags
def decode_base_mode(base_mode):
# Bit 7 (value 128): motors armed [§II.D.1]
armed = (base_mode & 128) != 0
# Bit 6 (value 64): manual mode enabled [§II.D.1]
manual = (base_mode & 64) != 0
# Bit 3 (value 8): guided mode enabled [§II.D.1]
guided = (base_mode & 8) != 0
# Bit 2 (value 4): autonomous (AUTO) mode enabled [§II.D.1]
auto = (base_mode & 4) != 0
return {"armed": armed, "manual": manual,
"guided": guided, "auto": auto}Hyperparameters
The paper has no training or tuning. The table lists the protocol values it states. "Derived" marks values we computed from field sizes in the paper; the paper does not state them.
| Name | Value | Where | Notes |
|---|---|---|---|
| v1 start byte | 0xFE | §II.C.1 tab. II | |
| v2 start byte | 0xFD | §II.C.2 | |
| payload size | up to 255 bytes | §II.C.1 §II.C.2 | |
| v1 frame size | 8 to 263 bytes | §II.C.1 | 8 + payload length; consistent with the field list (derived) |
| v2 frame size without signature | not stated | §II.C.2 | 12 + payload length if the header is 10 bytes (derived) |
| v2 message ID | 24 bits, up to 16777215 | §II.C.2 | |
| v1 message ID | 8 bits | §II.C.1 | |
| signature block | 13 bytes = LinkID 1 + timestamp 6 + tag 6 | §II.C.2 | |
| timestamp unit | 10 microseconds since 1 January 2015 GMT | §II.C.2 | |
| shared key | 32 bytes, symmetric | §II.C.2 | how it is combined into the tag is not stated |
| signed-frame clock window | 1 minute | §II.C.2 | |
| system IDs | 1 to 255; 255 used for ground stations | §II.C.1 tab. II | the paper says 1.0 allows 254 drones per ground station |
| component IDs | 0 to 255 | tab. II | the paper says 27 component types exist in 1.0; the basis is not given |
| HEARTBEAT period | about 1 s | §II.D.1 | "in general every second" |
| telemetry radio | 433, 868 or 915 MHz; up to 250 kbps | §II.B | |
| telemetry range | about 500 m typical | §II.B | "highly dependent on the environment"; tab. I lists 500 m to over 40 km |
| GPS scaling | lat and lon divided by 10^7 | §II.D.1 | |
| altitude unit | millimetres | §II.D.1 | |
| LOITER speed | 500 cm/s default | §II.E | |
| LOITER max acceleration | half of LOITER speed (2.5 m/s^2) | §II.E | the paper's stated default |
| LOITER arming | GPS 3D lock and HDOP below 2.0 | §II.E | |
| COMMAND_LONG | 11 fields | §II.D.2 | |
| MAV_CMD count | about 60 | §II.D.2 | |
| MAV_TYPE count | 33 | §II.D.1 |
Results
Not applicable. The paper is a survey and reports no new experiments or benchmark numbers. Results it cites from other work, attributed to those works and not re-checked here:
- Packet signing on an autopilot: about 26 microseconds of overhead per packet and 812 bytes of added firmware, from the cited work davanian2017diversity §IV.B.1.
- ICMP flooding of a MAVLink ground station and UAV, from the cited work kwon2018empirical: heartbeats arrived late and the UAV crashed without entering its fail-safe mode §III.B.3.
- A MAVLink-to-STANAG 4586 bridge tested in SITL, from Rodrigues17: only important messages (for example waypoints) were translated §V.A.
Paper vs code
No official code. The paper has no project page or code link in its text.
Its bibliography links ArduPilot, Pixhawk, vendor and specification pages,
and one GitHub repository (ArduPilot's MAVProxy). None of these belongs to the
paper's authors. GitHub searches: mavlink survey tutorial (0 results),
koubaa mavlink (0 results), mavlink survey (17 results; no owner is an
author or an author's lab). The paper has no method to compare with code.
Pitfalls
- Security claims contradict each other. §III.A and §III.B say MAVLink has no encryption and no native authentication §III.B. §IV says the protocol implements neither §IV. §II.C.2 describes an optional packet-signing mechanism that authenticates frames. Read "no authentication" as "no encryption, and only optional signing in MAVLink 2".
- Signature field lists differ. §II.C.2 gives the timestamp, the message and the key as inputs. §IV.B.1 lists "secret key, payload, link ID, header, CRC, and timestamp". Table V lists the same set in another order tab. V. The paper gives no order, so an implementer cannot take it from the paper. Use the MAVLink specification the implementation targets, and test against recorded traffic.
- CRC input byte count does not match the field list. The paper says the CRC covers "6+n+1" bytes after STX, with the last byte as the seed §II.C.1. Counting the fields named there gives five bytes after STX before the payload (LEN, SEQ, SYS, COMP, MSG), not six. The seed value itself and its per-message table are not in the paper.
- Checksum byte order not stated. The paper names CKA and CKB and says the signing runs "from LSB to MSB" tab. II without saying what that means for the 16-bit CRC.
- Message ID byte order not stated for the 3-byte MAVLink 2 message ID.
- Altitude examples disagree. The Riyadh absolute altitude is 612 m in §II.D.1 and 620 m in §II.D.2. Only the second is used in the mission example.
- Telemetry range is inconsistent. §II.B gives a typical range of 500 m. tab. I lists 50 m (Bluetooth), 500 m (SiK Radio v2), over 40 km (RFD900) and 3 to 5 km (Robsense). §VI.A says telemetry reaches 5 km.
- Table entries are wrong or unclear. The SET_HOME row in tab. III has the same description as GET_HOME. The TAKEOFF row says the altitude is in parameter 1, but its parameter column and the text say parameter 7.
- Figure caption is wrong. fig. 4 (global position) is captioned "System status message" in the source.
- Flight-mode prose is garbled. The LOITER and GUIDED passages say it is "not possible to arm ... only if" conditions hold. The intended meaning (arming needs a 3D GPS fix; LOITER also needs HDOP below 2.0) is clear from the context, but the sentences themselves do not state it cleanly §II.E.
- Paper section roadmap is out of date. The introduction says Section III covers threats and solutions, and Section IV is the literature. In the paper, threats are in III, solutions in IV, the literature in V, the software in VI and the conclusions in VII §I.
- Dated claims. §II.C says MAVLink 2.0 "is the current recommended version", which is a 2019 statement. The paper does not cover later changes. Check the current specification before implementing.
- Licence of MAVLink itself. The introduction says MAVLink was released under LGPL in 2009 §I. We have not checked that, and the card does not rely on it.
- Unstated tuning. ALT_HOLD's proportional gain is discussed only through a screenshot caption fig. 6. The paper gives no default value.
Lineage
- Builds on: the MAVLink 1.0 and 2.0 specifications, which the paper cites as its primary references §II.C.
- Compared against: not applicable (survey).
- Superseded by: not stated in this wiki.
- Related surveyed work with cards: none in this wiki yet.
Source and license
Adapted from “Micro Air Vehicle Link (MAVLink) in a Nutshell: A Survey” by Anis Koubaa, Azza Allouch, Maram Alajlan, Yasir Javed, Abdelfettah Belghith, Mohamed Khalgui (arXiv:1906.10641), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors.