162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci===========================
462306a36Sopenharmony_ciHow to use radiotap headers
562306a36Sopenharmony_ci===========================
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciPointer to the radiotap include file
862306a36Sopenharmony_ci------------------------------------
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ciRadiotap headers are variable-length and extensible, you can get most of the
1162306a36Sopenharmony_ciinformation you need to know on them from::
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci    ./include/net/ieee80211_radiotap.h
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ciThis document gives an overview and warns on some corner cases.
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciStructure of the header
1962306a36Sopenharmony_ci-----------------------
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciThere is a fixed portion at the start which contains a u32 bitmap that defines
2262306a36Sopenharmony_ciif the possible argument associated with that bit is present or not.  So if b0
2362306a36Sopenharmony_ciof the it_present member of ieee80211_radiotap_header is set, it means that
2462306a36Sopenharmony_cithe header for argument index 0 (IEEE80211_RADIOTAP_TSFT) is present in the
2562306a36Sopenharmony_ciargument area.
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci::
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci   < 8-byte ieee80211_radiotap_header >
3062306a36Sopenharmony_ci   [ <possible argument bitmap extensions ... > ]
3162306a36Sopenharmony_ci   [ <argument> ... ]
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciAt the moment there are only 13 possible argument indexes defined, but in case
3462306a36Sopenharmony_ciwe run out of space in the u32 it_present member, it is defined that b31 set
3562306a36Sopenharmony_ciindicates that there is another u32 bitmap following (shown as "possible
3662306a36Sopenharmony_ciargument bitmap extensions..." above), and the start of the arguments is moved
3762306a36Sopenharmony_ciforward 4 bytes each time.
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciNote also that the it_len member __le16 is set to the total number of bytes
4062306a36Sopenharmony_cicovered by the ieee80211_radiotap_header and any arguments following.
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ciRequirements for arguments
4462306a36Sopenharmony_ci--------------------------
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciAfter the fixed part of the header, the arguments follow for each argument
4762306a36Sopenharmony_ciindex whose matching bit is set in the it_present member of
4862306a36Sopenharmony_ciieee80211_radiotap_header.
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci - the arguments are all stored little-endian!
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci - the argument payload for a given argument index has a fixed size.  So
5362306a36Sopenharmony_ci   IEEE80211_RADIOTAP_TSFT being present always indicates an 8-byte argument is
5462306a36Sopenharmony_ci   present.  See the comments in ./include/net/ieee80211_radiotap.h for a nice
5562306a36Sopenharmony_ci   breakdown of all the argument sizes
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci - the arguments must be aligned to a boundary of the argument size using
5862306a36Sopenharmony_ci   padding.  So a u16 argument must start on the next u16 boundary if it isn't
5962306a36Sopenharmony_ci   already on one, a u32 must start on the next u32 boundary and so on.
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci - "alignment" is relative to the start of the ieee80211_radiotap_header, ie,
6262306a36Sopenharmony_ci   the first byte of the radiotap header.  The absolute alignment of that first
6362306a36Sopenharmony_ci   byte isn't defined.  So even if the whole radiotap header is starting at, eg,
6462306a36Sopenharmony_ci   address 0x00000003, still the first byte of the radiotap header is treated as
6562306a36Sopenharmony_ci   0 for alignment purposes.
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci - the above point that there may be no absolute alignment for multibyte
6862306a36Sopenharmony_ci   entities in the fixed radiotap header or the argument region means that you
6962306a36Sopenharmony_ci   have to take special evasive action when trying to access these multibyte
7062306a36Sopenharmony_ci   entities.  Some arches like Blackfin cannot deal with an attempt to
7162306a36Sopenharmony_ci   dereference, eg, a u16 pointer that is pointing to an odd address.  Instead
7262306a36Sopenharmony_ci   you have to use a kernel API get_unaligned() to dereference the pointer,
7362306a36Sopenharmony_ci   which will do it bytewise on the arches that require that.
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci - The arguments for a given argument index can be a compound of multiple types
7662306a36Sopenharmony_ci   together.  For example IEEE80211_RADIOTAP_CHANNEL has an argument payload
7762306a36Sopenharmony_ci   consisting of two u16s of total length 4.  When this happens, the padding
7862306a36Sopenharmony_ci   rule is applied dealing with a u16, NOT dealing with a 4-byte single entity.
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciExample valid radiotap header
8262306a36Sopenharmony_ci-----------------------------
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci::
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	0x00, 0x00, // <-- radiotap version + pad byte
8762306a36Sopenharmony_ci	0x0b, 0x00, // <- radiotap header length
8862306a36Sopenharmony_ci	0x04, 0x0c, 0x00, 0x00, // <-- bitmap
8962306a36Sopenharmony_ci	0x6c, // <-- rate (in 500kHz units)
9062306a36Sopenharmony_ci	0x0c, //<-- tx power
9162306a36Sopenharmony_ci	0x01 //<-- antenna
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ciUsing the Radiotap Parser
9562306a36Sopenharmony_ci-------------------------
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciIf you are having to parse a radiotap struct, you can radically simplify the
9862306a36Sopenharmony_cijob by using the radiotap parser that lives in net/wireless/radiotap.c and has
9962306a36Sopenharmony_ciits prototypes available in include/net/cfg80211.h.  You use it like this::
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci    #include <net/cfg80211.h>
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci    /* buf points to the start of the radiotap header part */
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci    int MyFunction(u8 * buf, int buflen)
10662306a36Sopenharmony_ci    {
10762306a36Sopenharmony_ci	    int pkt_rate_100kHz = 0, antenna = 0, pwr = 0;
10862306a36Sopenharmony_ci	    struct ieee80211_radiotap_iterator iterator;
10962306a36Sopenharmony_ci	    int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buflen);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	    while (!ret) {
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci		    ret = ieee80211_radiotap_iterator_next(&iterator);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci		    if (ret)
11662306a36Sopenharmony_ci			    continue;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci		    /* see if this argument is something we can use */
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		    switch (iterator.this_arg_index) {
12162306a36Sopenharmony_ci		    /*
12262306a36Sopenharmony_ci		    * You must take care when dereferencing iterator.this_arg
12362306a36Sopenharmony_ci		    * for multibyte types... the pointer is not aligned.  Use
12462306a36Sopenharmony_ci		    * get_unaligned((type *)iterator.this_arg) to dereference
12562306a36Sopenharmony_ci		    * iterator.this_arg for type "type" safely on all arches.
12662306a36Sopenharmony_ci		    */
12762306a36Sopenharmony_ci		    case IEEE80211_RADIOTAP_RATE:
12862306a36Sopenharmony_ci			    /* radiotap "rate" u8 is in
12962306a36Sopenharmony_ci			    * 500kbps units, eg, 0x02=1Mbps
13062306a36Sopenharmony_ci			    */
13162306a36Sopenharmony_ci			    pkt_rate_100kHz = (*iterator.this_arg) * 5;
13262306a36Sopenharmony_ci			    break;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci		    case IEEE80211_RADIOTAP_ANTENNA:
13562306a36Sopenharmony_ci			    /* radiotap uses 0 for 1st ant */
13662306a36Sopenharmony_ci			    antenna = *iterator.this_arg);
13762306a36Sopenharmony_ci			    break;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		    case IEEE80211_RADIOTAP_DBM_TX_POWER:
14062306a36Sopenharmony_ci			    pwr = *iterator.this_arg;
14162306a36Sopenharmony_ci			    break;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci		    default:
14462306a36Sopenharmony_ci			    break;
14562306a36Sopenharmony_ci		    }
14662306a36Sopenharmony_ci	    }  /* while more rt headers */
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	    if (ret != -ENOENT)
14962306a36Sopenharmony_ci		    return TXRX_DROP;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	    /* discard the radiotap header part */
15262306a36Sopenharmony_ci	    buf += iterator.max_length;
15362306a36Sopenharmony_ci	    buflen -= iterator.max_length;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	    ...
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci    }
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ciAndy Green <andy@warmcat.com>
160