RFtap is a simple protocol designed to provide Radio Frequency (RF) metadata about packets, such as:

  • Accurate signal and noise power
  • Accurate timing and phase information
  • Accurate Carrier and Doppler frequencies of every packet, and more.

RFtap bridges the gap between Software Defined Radio (SDR) platforms (such as GNU Radio, Pothos, liquidsdr, LuaRadio) and conventional network monitoring and packet analysis tools (such as Wireshark, TShark, tcpdump, Scapy), allowing the access and manipulation of novel RF metadata from packets while remaining within the comfortable and mature environment of conventional networking tools.

RFtap bridging the gap between SDR platforms and networking tools

The RFtap protocol is inspired by the radiotap protocol; however it is designed to encapsulate any type of packet (not just Wi-Fi), and preserve the exact RF attributes of each packet without loss of accuracy.

Sample RFtap attributes in Wireshark


Read about all the RFtap header, the various RFtap tags and field names in the RFtap specifications.

Using RFtap (as a Consumer)

The most natural way to process RFtap packets is through standard networking tools and file formats such as Wireshark, TShark, pcap files, editcap, mergecap, etc. Use Wireshark/TShark built-in RFtap dissector for filtering and analytics. Some examples:

Filter packets above a Signal-to-Noise ratio:

Filtering packets in Wireshark based on RF metadata

Print the transmitter MAC address and the received Doppler frequency (in Hertz) of each Wi-Fi packet:

$ tshark -i lo -q -T fields -e wlan.ta -e rftap.freqofs
Capturing on 'Loopback'
00:a0:cc:23:af:4a	837.9016071558
3a:34:52:c4:69:b8	13188.2628193125
3a:34:52:c4:69:b8	15857.2173677385
3a:34:52:c4:69:b8	9895.83786576986
c8:60:00:ba:95:65	3073.38777929544
34:4d:ea:89:75:b2	-6725.89638270438
3a:34:52:c4:69:b8	10878.7475619465

Using RFtap (as a Producer)

RFtap packets can be produced using GNU Radio RFtap encapsulation block. This block can be connected to any GNU Radio block that produces PDU messages (the grey-colored port in GNU Radio blocks). The encapsulation block automatically extracts common metadata fields from the PDU, encoding them into the appropriate RFtap fields.

See Tutorial: encapsulating RDS packets with RFtap:

Encapsulating RDS data into RFtap packets and sending them via UDP to Wireshark

Alternatively, RFtap packets can be easily created in any language, because of the simple structure:

struct rftap_hdr {
    le32 magic;  // signature: "RFta"
    le16 len32;  // length
    le16 flags;  // bitfield indicating presence of fields
    le32 data[];  // the rftap fields
} __attribute__((packed));

For example, to encode Signal-to-Noise (SNR) metadata for an arbitrary packet:

struct my_packet {
    // RFtap header + optional fields
    le32 magic;
    le16 len32;
    le16 flags;
    float snr;

    char packet_data[123];  // packet data
} __attribute__((packed));

void prepare_packet(my_packet *pkt) {
    pkt->magic = 0x61744652UL;  // fixed signature ("RFta" in hex)
    pkt->len32 = 3;  // we use 3x 32-bit words: magic, len+flags, snr
    pkt->flags = 0x0080;  // "SNR" field is present (bit #7 is ON)

    pkt->snr = 12.34;  // fill your Signal-to-Noise, in dB (decibels)
    pkt->data = // fill your packet data here.
    // Done! Packet is ready to be sent, or saved to pcap file...