2 * Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
5 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "file_wrappers.h"
32 /* platform-specific definitions for portability */
34 /* unsigned long long constants */
35 # define NS_IN_US G_GUINT64_CONSTANT(1000) /* nanoseconds-to-microseconds */
36 # define NS_IN_SEC G_GUINT64_CONSTANT(1000000000) /* nanoseconds-to-seconds */
37 # define US_IN_SEC G_GUINT64_CONSTANT(1000000) /* microseconds-to-seconds */
38 # define LL_ZERO G_GUINT64_CONSTANT(0) /* zero in unsigned long long */
41 * Fetch a 64-bit value in "Corey-endian" form.
43 #define pcoreytohll(p) ((guint64)*((const guint8 *)(p)+4)<<56| \
44 (guint64)*((const guint8 *)(p)+5)<<48| \
45 (guint64)*((const guint8 *)(p)+6)<<40| \
46 (guint64)*((const guint8 *)(p)+7)<<32| \
47 (guint64)*((const guint8 *)(p)+0)<<24| \
48 (guint64)*((const guint8 *)(p)+1)<<16| \
49 (guint64)*((const guint8 *)(p)+2)<<8| \
50 (guint64)*((const guint8 *)(p)+3)<<0)
53 * Fetch a 48-bit value in "Corey-endian" form; it's stored as
54 * a 64-bit Corey-endian value, with the upper 16 bits ignored.
56 #define pcorey48tohll(p) ((guint64)*((const guint8 *)(p)+6)<<40| \
57 (guint64)*((const guint8 *)(p)+7)<<32| \
58 (guint64)*((const guint8 *)(p)+0)<<24| \
59 (guint64)*((const guint8 *)(p)+1)<<16| \
60 (guint64)*((const guint8 *)(p)+2)<<8| \
61 (guint64)*((const guint8 *)(p)+3)<<0)
63 /* .vwr log file defines */
64 #define B_SIZE 32768 /* max var len message = 32 kB */
65 #define VT_FRAME 0 /* varlen msg is a frame */
66 #define VT_CPMSG 1 /* varlen msg is a CP<->PP msg */
67 #define VT_UNKNOWN -1 /* varlen msg is unknown */
68 #define MAX_TRACKED_CLIENTS 1024 /* track 1024 clients */
69 #define MAX_TRACKED_FLOWS 65536 /* and 64K flows */
72 * The file consists of a sequence of records.
73 * A record begins with a 16-byte header, the first 8 bytes of which
74 * begin with a byte containing a command plus transmit-receive flags.
76 * Following that are two big-endian 32-bit quantities; for some records
77 * one or the other of them is the length of the rest of the record.
78 * Other records contain only the header.
80 #define VW_RECORD_HEADER_LENGTH 16
82 /* Command byte values */
83 #define COMMAND_RX 0x21
84 #define COMMAND_TX 0x31
85 #define COMMAND_RFN 0x30
86 #define COMMAND_RF 0x38
87 #define COMMAND_RFRX 0x39
90 * The data in packet records begins with a sequence of metadata headers.
92 * For packet records from FPGA versions < 48:
94 * The first header is the IxVeriWave common header, and that's
95 * followed either by a WLAN metadata header or an Ethernet
96 * metadata header. The port type field indicates whether it's
97 * a WLAN packet or an Ethernet packet. Following that may, for
98 * WLAN, be 1 octet of information from the FPGA and 16 bytes of
99 * data including the PLCP header. After that comes the WLAN or
100 * Ethernet frame, beginning with the MAC header.
102 * For packet records from FPGA versions >= 48:
104 * The first header contains only a 1-octet port type value, which
105 * has a packet type value in the upper 4 bits and zero in the lower
106 * 4 bits. NOTE: this is indistinguishable from an old FPGA header
107 * if the packet type value is 0.
109 * If the packet type value isn't 3, the port type value is followed
110 * by a 1-octet FPGA version number, which is followed by a timestamp
113 * If the packet type value is 3 or 4, the next item is an RF metadata
114 * header. For type 3, that immediately follows the port number octet,
115 * otherwise it immediately follows the timestamp header.
117 * If the packet type isn't 3, the next item is a WLAN metadata header,
118 * in a format different from the WLAN metadata header for FPGA versions
119 * < 48. That is followed by a PLCP header, which is followed by a
120 * header giving additional layer 2 through 4 metadata.
122 * Following those headers is the WLAN or Ethernet frame, beginning with
127 * IxVeriWave common header:
129 * 1 octet - port type
130 * 1 octet - FPGA version, or 0
131 * 2 octets - length of the common header
132 * 2 octets - MSDU length
135 * 2 octets - flow sequence number
136 * 4 octets - latency or 0
137 * 4 octets - lower 32 bits of signature time stamp
138 * 8 octets - start time
139 * 8 octets - end time
140 * 4 octets - delta(?) time
143 /* Size of the IxVeriWave common header */
144 #define STATS_COMMON_FIELDS_LEN (1+1+2+2+4+2+2+4+4+8+8+4)
148 #define ETHERNET_PORT 1
150 /* For VeriWave WLAN and Ethernet metadata headers vw_flags field */
151 #define VW_FLAGS_TXF 0x01 /* frame was transmitted */
152 #define VW_FLAGS_FCSERR 0x02 /* FCS error detected */
155 * VeriWave WLAN metadata header:
157 * 2 octets - header length
159 * 2 octets - channel flags
160 * 2 octets - PHY rate
161 * 1 octet - PLCP type
162 * 1 octet - MCS index
163 * 1 octet - number of spatial streams
165 * 1 octet - antenna b signal power, or 100 if missing
166 * 1 octet - antenna c signal power, or 100 if missing
167 * 1 octet - antenna d signal power, or 100 if missing
169 * 2 octets - VeriWave flags
175 /* Size of the VeriWave WLAN metadata header */
176 #define EXT_WLAN_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
178 /* Flags, for rflags field */
179 #define FLAGS_SHORTPRE 0x0002 /* sent/received with short preamble */
180 #define FLAGS_WEP 0x0004 /* sent/received with WEP encryption */
181 #define FLAGS_CHAN_HT 0x0040 /* In HT mode */
182 #define FLAGS_CHAN_VHT 0x0080 /* VHT Mode */
183 #define FLAGS_CHAN_SHORTGI 0x0100 /* Short guard interval */
184 #define FLAGS_CHAN_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
185 #define FLAGS_CHAN_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
186 #define FLAGS_CHAN_160MHZ 0x0800 /* 160 Mhz channel bandwidth */
188 /* Channel flags, for channel flags field */
189 #define CHAN_CCK 0x0020 /* CCK channel */
190 #define CHAN_OFDM 0x0040 /* OFDM channel */
192 /* For VeriWave WLAN metadata header vw_flags field */
193 #define VW_FLAGS_RETRERR 0x04 /* excess retry error detected */
194 #define VW_FLAGS_DCRERR 0x10 /* decrypt error detected (WLAN) */
195 #define VW_FLAGS_ENCMSK 0x60 /* encryption type mask */
196 /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
197 #define VW_FLAGS_IS_WEP 0x20 /* WEP */
198 #define VW_FLAGS_IS_TKIP 0x40 /* TKIP */
199 #define VW_FLAGS_IS_CCMP 0x60 /* CCMP */
202 * VeriWave Ethernet metadata header:
204 * 2 octets - header length
205 * 2 octets - VeriWave flags
208 * 4 octets - layer 4 ID
211 * Ethernet frame follows, beginning with the MAC header
214 /* Size of the VeriWave Ethernet metadata header */
215 #define EXT_ETHERNET_FIELDS_LEN (2+2+2+4+4+4)
218 * OCTO timestamp header.
220 * 4 octets - latency or 0
221 * 4 octets - lower 32 bits of signature time stamp
222 * 8 octets - start time
223 * 8 octets - end time
224 * 4 octets - delta(?) time
227 /* Size of Timestamp header */
228 #define OCTO_TIMESTAMP_FIELDS_LEN (4+4+8+8+4+4)
231 * OCTO layer 1-4 header:
233 * 2 octets - header length
235 * 1 octet - number of spatial streams
236 * 2 octets - PHY rate
239 * 1 octet - antenna b signal power, or 100 if missing
240 * 1 octet - antenna c signal power, or 100 if missing
241 * 1 octet - antenna d signal power, or 100 if missing
242 * 1 octet - signal bandwidth mask
243 * 1 octet - antenna port energy detect and VU_MASK
244 * 1 octet - L1InfoC or 0
245 * 2 octets - MSDU length
247 * 4 octets - BM, BV, CV, BSSID and ClientID
248 * 2 octets - FV, QT, HT, L4V, TID and WLAN type
249 * 1 octets - flow sequence number
251 * 2 octets - layer 4 ID
252 * 4 octets - payload decode
257 /* Size of Layer-1, PLCP, and Layer-2/4 header incase of OCTO version FPGA */
258 #define OCTO_LAYER1TO4_LEN (2+14+16+23)
261 * OCTO modified RF layer:
264 * 3 octets - unused (zero)
265 * 8 octets - noise for 4 ports
266 * 8 octets - signal/noise ration for 4 ports
267 * 8 octets - PFE for 4 ports
268 * 8 octets - EVM SIG data for 4 ports
269 * 8 octets - EVM SIG pilot for 4 ports
270 * 8 octets - EVM Data data for 4 ports
271 * 8 octets - EVM Data pilot for 4 ports
272 * 8 octets - EVM worst symbol for 4 ports
273 * 8 octets - CONTEXT_P for 4 ports
276 * 24 octets of additional data
279 /* Size of RF header, if all fields were supplied */
280 #define OCTO_RF_MOD_ACTUAL_LEN 100 /* */
282 /* Size of RF header with the fields we do supply */
283 #define OCTO_MODIFIED_RF_LEN 76 /* 24 bytes of RF are not displayed*/
285 /*Offset of differnt parameters of RF header for port-1*/
286 #define RF_PORT_1_NOISE_OFF 4
287 #define RF_PORT_1_SNR_OFF 6
288 #define RF_PORT_1_PFE_OFF 8
289 #define RF_PORT_1_CONTEXT_OFF 10
290 #define RF_PORT_1_EVM_SD_SIG_OFF 12
291 #define RF_PORT_1_EVM_SP_SIG_OFF 14
292 #define RF_PORT_1_EVM_SD_DATA_OFF 16
293 #define RF_PORT_1_EVM_SP_DATA_OFF 18
294 #define RF_PORT_1_DSYMBOL_IDX_OFF 22
295 #define RF_INTER_PORT_GAP_OFF 24 /*As size of RF information per port is 24 bytes*/
296 #define RF_NUMBER_OF_PORTS 4
298 /* FPGA-generated frame buffer STATS block offsets and definitions */
300 /* definitions for v2.2 frames, Ethernet format */
301 #define v22_E_STATS_LEN 44 /* length of stats block trailer */
302 #define v22_E_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
303 #define v22_E_MTYPE_OFF 1 /* offset of modulation type */
304 #define v22_E_VCID_OFF 2 /* offset of VC ID */
305 #define v22_E_FLOWSEQ_OFF 4 /* offset of signature sequence number */
306 #define v22_E_FLOWID_OFF 5 /* offset of flow ID */
307 #define v22_E_OCTET_OFF 8 /* offset of octets */
308 #define v22_E_ERRORS_OFF 10 /* offset of error vector */
309 #define v22_E_PATN_OFF 12 /* offset of pattern match vector */
310 #define v22_E_L4ID_OFF 12
311 #define v22_E_IPLEN_OFF 14
312 #define v22_E_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
313 #define v22_E_RSSI_OFF 21 /* RSSI (NOTE: invalid for Ethernet) */
314 #define v22_E_STARTT_OFF 20 /* offset of start time, 64 bits */
315 #define v22_E_ENDT_OFF 28 /* offset of end time, 64 bits */
316 #define v22_E_LATVAL_OFF 36 /* offset of latency, 32 bits */
317 #define v22_E_INFO_OFF 40 /* NO INFO FIELD IN ETHERNET STATS! */
318 #define v22_E_DIFFERENTIATOR_OFF 0 /* offset to determine whether */
319 /* eth/802.11, 8 bits */
321 #define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
322 #define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
323 #define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
324 #define v22_E_MT_100_FULL 3 /* 100 Mb/s full-duplex */
325 #define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
326 #define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
329 #define v22_E_FCS_ERROR 0x0002 /* FCS error flag in error vector */
330 #define v22_E_CRYPTO_ERR 0x1f00 /* RX decrypt error flags (UNUSED) */
331 #define v22_E_SIG_ERR 0x0004 /* signature magic byte mismatch */
332 #define v22_E_PAYCHK_ERR 0x0008 /* payload checksum failure */
333 #define v22_E_RETRY_ERR 0x0400 /* excessive retries on TX fail (UNUSED)*/
335 /* Masks and defines */
336 #define v22_E_IS_RX 0x08 /* TX/RX bit in STATS block */
337 #define v22_E_MT_MASK 0x07 /* modulation type mask (UNUSED) */
339 #define v22_E_VCID_MASK 0x03ff /* VC ID is only 10 bits */
341 #define v22_E_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
343 #define v22_E_DIFFERENTIATOR_MASK 0x3F /* mask to differentiate ethernet from */
345 /* Bits in FRAME_TYPE field */
346 #define v22_E_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
347 #define v22_E_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
348 #define v22_E_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
349 #define v22_E_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
351 /* Bits in MTYPE field (WLAN only) */
352 #define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
354 #define v22_E_IS_VLAN 0x00200000
356 #define v22_E_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted (UNUSED) */
357 #define v22_E_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted (UNUSED) */
359 #define v22_E_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
361 #define v22_E_IS_ETHERNET 0x00700000 /* bits set in frame type if ethernet */
362 #define v22_E_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
364 /* definitions for v2.2 frames, WLAN format for VW510006 FPGA*/
365 #define v22_W_STATS_LEN 64 /* length of stats block trailer */
366 #define v22_W_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
367 #define v22_W_MTYPE_OFF 1 /* offset of modulation type */
368 #define v22_W_VCID_OFF 2 /* offset of VC ID */
369 #define v22_W_FLOWSEQ_OFF 4 /* offset of signature sequence number */
370 #define v22_W_FLOWID_OFF 5 /* offset of flow ID */
371 #define v22_W_OCTET_OFF 8 /* offset of octets */
372 #define v22_W_ERRORS_OFF 10 /* offset of error vector */
373 #define v22_W_PATN_OFF 12
374 #define v22_W_L4ID_OFF 12
375 #define v22_W_IPLEN_OFF 14
376 #define v22_W_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
377 #define v22_W_RSSI_OFF 21 /* RSSI (NOTE: RSSI must be negated!) */
378 #define v22_W_STARTT_OFF 24 /* offset of start time, 64 bits */
379 #define v22_W_ENDT_OFF 32 /* offset of end time, 64 bits */
380 #define v22_W_LATVAL_OFF 40 /* offset of latency, 32 bits */
381 #define v22_W_INFO_OFF 54 /* offset of INFO field, 16 LSBs */
382 #define v22_W_DIFFERENTIATOR_OFF 20 /* offset to determine whether */
383 /* eth/802.11, 32 bits */
385 #define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
387 /* Modulation types */
388 #define v22_W_MT_CCKL 0 /* CCK modulation, long preamble */
389 #define v22_W_MT_CCKS 1 /* CCK modulation, short preamble */
390 #define v22_W_MT_OFDM 2 /* OFDM modulation */
392 /* Bits in FRAME_TYPE field */
393 #define v22_W_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
394 #define v22_W_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
395 #define v22_W_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
396 #define v22_W_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
398 /* Bits in MTYPE field (WLAN only) */
399 #define v22_W_IS_QOS 0x80 /* QoS */
402 #define v22_W_FCS_ERROR 0x0002 /* FCS error flag in error vector */
403 #define v22_W_CRYPTO_ERR 0x1f00 /* RX decrypt error flags */
404 #define v22_W_SIG_ERR 0x0004 /* signature magic byte mismatch */
405 #define v22_W_PAYCHK_ERR 0x0008 /* payload checksum failure */
406 #define v22_W_RETRY_ERR 0x0400 /* excessive retries on TX failure */
408 /* Masks and defines */
409 #define v22_W_IS_RX 0x08 /* TX/RX bit in STATS block */
410 #define v22_W_MT_MASK 0x07 /* modulation type mask */
412 #define v22_W_VCID_MASK 0x01ff /* VC ID is only 9 bits */
414 #define v22_W_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
416 #define v22_W_DIFFERENTIATOR_MASK 0xf0ff /* mask to differentiate ethernet from */
419 #define v22_W_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted bits */
420 #define v22_W_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted bits */
423 #define v22_W_WEPTYPE 0x0001 /* WEP frame */
424 #define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
425 #define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
426 #define v22_W_MPDU_OF_A_MPDU 0x0400 /* MPDU of A-MPDU */
427 #define v22_W_FIRST_MPDU_OF_A_MPDU 0x0800 /* first MPDU of A-MPDU */
428 #define v22_W_LAST_MPDU_OF_A_MPDU 0x1000 /* last MPDU of A-MPDU */
429 #define v22_W_MSDU_OF_A_MSDU 0x2000 /* MSDU of A-MSDU */
430 #define v22_W_FIRST_MSDU_OF_A_MSDU 0x4000 /* first MSDU of A-MSDU */
431 #define v22_W_LAST_MSDU_OF_A_MSDU 0x8000 /* last MSDU of A-MSDU */
433 /* All aggregation flags */
434 #define v22_W_AGGREGATE_FLAGS \
435 (v22_W_MPDU_OF_A_MPDU | \
436 v22_W_FIRST_MPDU_OF_A_MPDU | \
437 v22_W_LAST_MPDU_OF_A_MPDU | \
438 v22_W_MSDU_OF_A_MSDU | \
439 v22_W_FIRST_MSDU_OF_A_MSDU | \
440 v22_W_LAST_MSDU_OF_A_MSDU)
442 #define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
444 #define v22_W_IS_ETHERNET 0x00100000 /* bits set in frame type if ethernet */
445 #define v22_W_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
447 /* definitions for VW510021 FPGA, WLAN format */
450 8 bytes of stat block
451 plcp stuff (11 bytes plcp + 1 byte pad)
453 remaining 48 bytes of stat block
455 /* offsets in the stats block */
456 #define vVW510021_W_STATS_HEADER_LEN 8 /* length of stats block header at beginning of record data */
457 #define vVW510021_W_STATS_TRAILER_LEN 48 /* length of stats block trailer after the plcp portion*/
458 #define vVW510021_W_STARTT_OFF 0 /* offset of start time, 64 bits */
459 #define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
460 #define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
461 #define vVW510021_W_VALID_OFF 20 /* 2 Bytes with different validity bits */
462 #define vVW510021_W_INFO_OFF 22 /* offset of INFO field, 16 LSBs */
463 #define vVW510021_W_FRAME_TYPE_OFF 24
464 #define vVW510021_W_L4ID_OFF 28
465 #define vVW510021_W_IPLEN_OFF 30 /* offset of IP Total Length field */
466 #define vVW510021_W_FLOWSEQ_OFF 32 /* offset of signature sequence number */
467 #define vVW510021_W_FLOWID_OFF 33 /* offset of flow ID */
468 #define vVW510021_W_LATVAL_OFF 36 /* offset of delay/flowtimestamp, 32b */
469 #define vVW510021_W_DEBUG_OFF 40 /* offset of debug, 16 bits */
470 #define S2_W_FPGA_VERSION_OFF 44 /* offset of fpga version, 16 bits */
471 #define vVW510021_W_MATCH_OFF 47 /* offset of pattern match vector */
473 /* offsets in the header block */
474 #define vVW510021_W_HEADER_LEN 16 /* length of FRAME header */
475 #define vVW510021_W_RXTX_OFF 0 /* rxtx offset, cmd byte of header */
476 #define vVW510021_W_HEADER_VERSION_OFF 9 /* version, 2bytes */
477 #define vVW510021_MSG_LENGTH_OFF 10 /* MSG LENGTH, 2bytes */
478 #define vVW510021_W_DEVICE_TYPE_OFF 8 /* version, 2bytes */
480 /* offsets that occur right after the header */
481 #define vVW510021_W_AFTERHEADER_LEN 8 /* length of STATs info directly after header */
482 #define vVW510021_W_L1P_1_OFF 0 /* offset of 1st byte of layer one info */
483 #define vVW510021_W_L1P_2_OFF 1 /* offset of 2nd byte of layer one info */
484 #define vVW510021_W_MTYPE_OFF vVW510021_W_L1P_2_OFF
485 #define vVW510021_W_PREAMBLE_OFF vVW510021_W_L1P_1_OFF
486 #define vVW510021_W_RSSI_TXPOWER_OFF 2 /* RSSI (NOTE: RSSI must be negated!) */
487 #define vVW510021_W_MSDU_LENGTH_OFF 3 /* 7:0 of length, next byte 11:8 in top 4 bits */
488 #define vVW510021_W_BVCV_VALID_OFF 4 /* BV,CV Determine validaity of bssid and txpower */
489 #define vVW510021_W_VCID_OFF 6 /* offset of VC (client) ID */
490 #define vVW510021_W_PLCP_LENGTH_OFF 12 /* LENGTH field in the plcp header */
492 /* Masks and defines */
493 #define vVW510021_W_IS_BV 0x04 /* BV bit in STATS block */
494 #define vVW510021_W_IS_CV 0x02 /* BV bit in STATS block */
495 #define vVW510021_W_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else 0) */
496 #define vVW510021_W_QOS_VALID 0x4000
497 #define vVW510021_W_HT_VALID 0x2000
498 #define vVW510021_W_L4ID_VALID 0x1000
499 #define vVW510021_W_MCS_MASK 0x3f /* mcs index (a/b) type mask */
500 #define vVW510021_W_MOD_SCHEME_MASK 0x3f /* modulation type mask */
501 #define vVW510021_W_PLCPC_MASK 0x03 /* PLPCP type mask */
502 #define vVW510021_W_SEL_MASK 0x80
503 #define vVW510021_W_WEP_MASK 0x0001
504 #define vVW510021_W_CBW_MASK 0xC0
506 #define vVW510024_W_VCID_MASK 0x03ff /* VC ID is only 10 bits */
508 #define vVW510021_W_MT_SEL_LEGACY 0x00
510 #define vVW510021_W_IS_WEP 0x0001
512 /* L1p byte 1 info */
514 /* Common to Series II and Series III */
516 #define vVW510021_W_IS_LONGPREAMBLE 0x40 /* short/long preamble bit */
517 #define vVW510021_W_IS_LONGGI 0x40 /* short/long guard interval bit */
522 * Pre-HT - contains rate index.
524 #define vVW510021_W_S2_RATE_INDEX(l1p_1) ((l1p_1) & 0x3f) /* rate index for pre-HT */
527 * HT - contains MCS index.
529 * XXX - MCS indices for HT go up to 76, which doesn't fit in 6 bits;
530 * either the mask is wrong, or the hardware can't receive packets
531 * with an MCS of 64 through 76, or the hardware can but misreports
534 #define vVW510021_W_S2_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
537 * VHT - contains MCS index and number of spatial streams.
538 * The number of spatial streams from the FPGA is zero-based, so we add
541 #define vVW510021_W_S2_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index for VHT */
542 #define vVW510021_W_S2_NSS_VHT(l1p_1) (((l1p_1) >> 4) + 1) /* NSS */
547 * Pre-HT - contains rate index.
549 #define vVW510021_W_S3_RATE_INDEX(l1p_1) ((l1p_1) & 0x3f)
552 * HT - contains MCS index.
554 * XXX - MCS indices for HT go up to 76, which doesn't fit in 6 bits;
555 * either the mask is wrong, or the hardware can't receive packets
556 * with an MCS of 64 through 76, or the hardware can but misreports
559 #define vVW510021_W_S3_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
562 * VHT - contains MCS index and number of spatial streams.
563 * The number of spatial streams from the FPGA is zero-based, so we add
566 #define vVW510021_W_S3_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index */
567 #define vVW510021_W_S3_NSS_VHT(l1p_1) ((((l1p_1) >> 4) & 0x03) + 1) /* NSS */
569 /* L1p byte 2 info */
571 /* Common to Series II and Series III */
572 #define vVW510021_W_BANDWIDTH_VHT(l1p_2) (((l1p_2) >> 4) & 0xf)
573 /* 3 = 40 MHz, 4 = 80 MHz; what about 20 and 160 MHz? */
576 #define vVW510021_W_S2_PLCP_TYPE(l1p_2) ((l1p_2) & 0x03) /* PLCP type */
579 #define vVW510021_W_S3_PLCP_TYPE(l1p_2) ((l1p_2) & 0x0f) /* PLCP type */
582 #define vVW510021_W_PLCP_LEGACY 0x00 /* pre-HT (11b/a/g) */
583 #define vVW510021_W_PLCP_MIXED 0x01 /* HT, mixed (11n) */
584 #define vVW510021_W_PLCP_GREENFIELD 0x02 /* HT, greenfield (11n) */
585 #define vVW510021_W_PLCP_VHT_MIXED 0x03 /* VHT (11ac) */
587 /* Bits in FRAME_TYPE field */
588 #define vVW510021_W_IS_TCP 0x01000000 /* TCP */
589 #define vVW510021_W_IS_UDP 0x00100000 /* UDP */
590 #define vVW510021_W_IS_ICMP 0x00001000 /* ICMP */
591 #define vVW510021_W_IS_IGMP 0x00010000 /* IGMP */
593 #define vVW510021_W_HEADER_VERSION 0x00
594 #define vVW510021_W_DEVICE_TYPE 0x15
595 #define vVW510021_W_11n_DEVICE_TYPE 0x20
596 #define S2_W_FPGA_VERSION 0x000C
597 #define vVW510021_W_11n_FPGA_VERSION 0x000D
600 #define vVW510021_W_FCS_ERROR 0x01
602 #define vVW510021_W_CRYPTO_ERROR 0x50000
604 #define vVW510021_W_WEPTYPE 0x0001 /* WEP frame */
605 #define vVW510021_W_TKIPTYPE 0x0002 /* TKIP frame */
606 #define vVW510021_W_CCMPTYPE 0x0004 /* CCMP frame */
608 /* definitions for VW510024 FPGA, wired ethernet format */
611 52 bytes of stats block trailer
613 /* offsets in the stats block */
614 #define vVW510024_E_STATS_LEN 48 /* length of stats block trailer */
615 #define vVW510024_E_MSDU_LENGTH_OFF 0 /* MSDU 16 BITS */
616 #define vVW510024_E_BMCV_VALID_OFF 2 /* BM,CV Determine validITY */
617 #define vVW510024_E_VCID_OFF 2 /* offset of VC (client) ID 13:8, */
619 #define vVW510024_E_STARTT_OFF 4 /* offset of start time, 64 bits */
620 #define vVW510024_E_ENDT_OFF 12 /* offset of end time, 64 bits */
621 #define vVW510024_E_ERRORS_OFF 22 /* offset of error vector */
622 #define vVW510024_E_VALID_OFF 24 /* 2 Bytes with different validity bits */
623 #define vVW510024_E_INFO_OFF 26 /* offset of INFO field, 16 LSBs */
624 #define vVW510024_E_FRAME_TYPE_OFF 28
625 #define vVW510024_E_L4ID_OFF 32
626 #define vVW510024_E_IPLEN_OFF 34
627 #define vVW510024_E_FLOWSEQ_OFF 36 /* offset of signature sequence number */
628 #define vVW510024_E_FLOWID_OFF 37 /* offset of flow ID */
629 #define vVW510024_E_LATVAL_OFF 40 /* offset of delay/flowtimestamp, 32 bits */
630 #define vVW510024_E_FPGA_VERSION_OFF 20 /* offset of fpga version, 16 bits */
631 #define vVW510024_E_MATCH_OFF 51 /* offset of pattern match vector */
633 /* offsets in the header block */
634 #define vVW510024_E_HEADER_LEN vVW510021_W_HEADER_LEN /* length of FRAME header */
635 #define vVW510024_E_RXTX_OFF vVW510021_W_RXTX_OFF /* rxtx offset, cmd byte */
636 #define vVW510024_E_HEADER_VERSION_OFF 16 /* version, 2bytes */
637 #define vVW510024_E_MSG_LENGTH_OFF vVW510021_MSG_LENGTH_OFF /* MSG LENGTH, 2bytes */
638 #define vVW510024_E_DEVICE_TYPE_OFF vVW510021_W_DEVICE_TYPE_OFF /* Device Type, 2bytes */
640 /* Masks and defines */
641 #define vVW510024_E_IS_BV 0x80 /* Bm bit in STATS block */
642 #define vVW510024_E_IS_CV 0x40 /* cV bit in STATS block */
643 #define vVW510024_E_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else force to 0) */
644 #define vVW510024_E_QOS_VALID 0x0000 /** not valid for ethernet **/
645 #define vVW510024_E_L4ID_VALID 0x1000
646 #define vVW510024_E_CBW_MASK 0xC0
647 #define vVW510024_E_VCID_MASK 0x3FFF /* VCID is only 14 bits */
649 #define vVW510024_E_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
650 #define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
651 #define vVW510024_E_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
652 #define vVW510024_E_IS_IGMP 0x00010000
653 #define vVW510024_E_IS_VLAN 0x00004000
655 #define vVW510024_E_HEADER_VERSION 0x00
656 #define vVW510024_E_DEVICE_TYPE 0x18
657 #define vVW510024_E_FPGA_VERSION 0x0001
659 #define FPGA_VER_NOT_APPLICABLE 0
661 #define UNKNOWN_FPGA 0
664 #define vVW510012_E_FPGA 3
665 #define vVW510024_E_FPGA 4
668 /* the flow signature is:
670 0 Magic Number (0xDD)
671 1 Chassis Number[7:0]
677 7 Flow Sequence Number[7:0]
688 #define SIG_SIZE 16 /* size of signature field, bytes */
689 #define SIG_FID_OFF 4 /* offset of flow ID in signature */
690 #define SIG_FSQ_OFF 7 /* offset of flow seqnum in signature */
691 #define SIG_TS_OFF 8 /* offset of flow seqnum in signature */
695 /*--------------------------------------------------------------------------------------*/
696 /* Per-capture file private data structure */
699 /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
700 /* version number of .vwr file, and are set up by setup_defaults() */
701 guint32 STATS_LEN; /* length of stats block trailer */
702 guint32 STATS_START_OFF; /* STATS OFF AFTER HEADER */
703 guint32 VALID_OFF; /* bit 6 (0x40) is flow-is-valid flag */
704 guint32 MTYPE_OFF; /* offset of modulation type */
705 guint32 VCID_OFF; /* offset of VC ID */
706 guint32 FLOWSEQ_OFF; /* offset of signature sequence number */
707 guint32 FLOWID_OFF; /* offset of flow ID */
708 guint32 OCTET_OFF; /* offset of octets */
709 guint32 ERRORS_OFF; /* offset of error vector */
710 guint32 PATN_OFF; /* offset of pattern match vector */
711 guint32 RSSI_OFF; /* RSSI (NOTE: RSSI must be negated!) */
712 guint32 STARTT_OFF; /* offset of start time, 64 bits */
713 guint32 ENDT_OFF; /* offset of end time, 64 bits */
714 guint32 LATVAL_OFF; /* offset of latency, 32 bits */
715 guint32 INFO_OFF; /* offset of INFO field, 16 bits */
716 guint32 L1P_1_OFF; /* offset 1ST Byte of l1params */
717 guint32 L1P_2_OFF; /* offset 2nd Byte of l1params */
718 guint32 L4ID_OFF; /* LAYER 4 id offset*/
719 guint32 IPLEN_OFF; /* */
720 guint32 PLCP_LENGTH_OFF; /* offset of length field in the PLCP header */
721 guint32 FPGA_VERSION_OFF; /* offset of fpga version field, 16 bits */
722 guint32 HEADER_VERSION_OFF; /* offset of header version, 16 bits */
723 guint32 RXTX_OFF; /* offset of CMD bit, rx or tx */
724 guint32 FRAME_TYPE_OFF;
726 /* other information about the file in question */
727 guint32 MT_10_HALF; /* 10 Mb/s half-duplex */
728 guint32 MT_10_FULL; /* 10 Mb/s full-duplex */
729 guint32 MT_100_HALF; /* 100 Mb/s half-duplex */
730 guint32 MT_100_FULL; /* 100 Mb/s full-duplex */
731 guint32 MT_1G_HALF; /* 1 Gb/s half-duplex */
732 guint32 MT_1G_FULL; /* 1 Gb/s full-duplex */
733 guint32 FCS_ERROR; /* FCS error in frame */
734 guint32 CRYPTO_ERR; /* RX decrypt error flags */
735 guint32 PAYCHK_ERR; /* payload checksum failure */
736 guint32 RETRY_ERR; /* excessive retries on TX failure */
737 guint8 IS_RX; /* TX/RX bit in STATS block */
738 guint8 MT_MASK; /* modulation type mask */
739 guint16 VCID_MASK; /* VC ID might not be a full 16 bits */
740 guint32 FLOW_VALID; /* flow-is-valid flag (else force to 0) */
742 guint32 RX_DECRYPTS; /* RX-frame-was-decrypted bits */
743 guint32 TX_DECRYPTS; /* TX-frame-was-decrypted bits */
744 guint32 FC_PROT_BIT; /* Protected Frame bit in FC1 of frame */
745 guint32 MT_CCKL; /* CCK modulation, long preamble */
746 guint32 MT_CCKS; /* CCK modulation, short preamble */
747 guint32 MT_OFDM; /* OFDM modulation */
748 guint32 MCS_INDEX_MASK; /* mcs index type mask */
749 guint32 FPGA_VERSION;
750 guint32 WEPTYPE; /* frame is WEP */
751 guint32 TKIPTYPE; /* frame is TKIP */
752 guint32 CCMPTYPE; /* frame is CCMP */
760 guint32 OCTO_VERSION;
764 * NSS for various MCS values.
766 #define MAX_HT_MCS 76
767 static guint nss_for_mcs[MAX_HT_MCS+1] = {
768 1, 1, 1, 1, 1, 1, 1, 1, /* 0-7 */
769 2, 2, 2, 2, 2, 2, 2, 2, /* 8-15 */
770 3, 3, 3, 3, 3, 3, 3, 3, /* 16-23 */
771 4, 4, 4, 4, 4, 4, 4, 4, /* 24-31 */
773 2, 2, 2, 2, 2, 2, /* 33-38 */
774 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 39-52 */
775 4, 4, 4, 4, 4, 4, /* 53-58 */
776 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 /* 59-76 */
779 /* internal utility functions */
780 static int decode_msg(vwr_t *vwr, register guint8 *, int *, int *, int *);
781 static guint8 get_ofdm_rate(const guint8 *);
782 static guint8 get_cck_rate(const guint8 *plcp);
783 static void setup_defaults(vwr_t *, guint16);
785 static gboolean vwr_read(wtap *, int *, gchar **, gint64 *);
786 static gboolean vwr_seek_read(wtap *, gint64, struct wtap_pkthdr *phdr,
787 Buffer *, int *, gchar **);
789 static gboolean vwr_read_rec_header(vwr_t *, FILE_T, int *, int *, int *, int *, gchar **);
790 static gboolean vwr_process_rec_data(FILE_T fh, int rec_size,
791 struct wtap_pkthdr *phdr, Buffer *buf,
792 vwr_t *vwr, int IS_TX, int log_mode, int *err,
795 static int vwr_get_fpga_version(wtap *, int *, gchar **);
797 static gboolean vwr_read_s1_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
798 const guint8 *, int, int *, gchar **);
799 static gboolean vwr_read_s2_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
800 const guint8 *, int, int, int *,
802 /* For FPGA version >= 48 (OCTO Platform), following function will be used */
803 static gboolean vwr_read_s3_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
804 const guint8 *, int, int, int, int *,
806 static gboolean vwr_read_rec_data_ethernet(vwr_t *, struct wtap_pkthdr *,
807 Buffer *, const guint8 *, int,
808 int, int *, gchar **);
810 static int find_signature(const guint8 *, int, int, register guint32, register guint8);
811 static guint64 get_signature_ts(const guint8 *, int);
812 static float get_legacy_rate(guint8);
813 static float get_ht_rate(guint8, guint16);
814 static float get_vht_rate(guint8, guint16, guint8);
816 /* Open a .vwr file for reading */
817 /* This does very little, except setting the wiretap header for a VWR file type */
818 /* and setting the timestamp precision to microseconds. */
820 wtap_open_return_val vwr_open(wtap *wth, int *err, gchar **err_info)
827 fpgaVer = vwr_get_fpga_version(wth, err, err_info);
829 return WTAP_OPEN_ERROR; /* I/O error */
831 if (fpgaVer == UNKNOWN_FPGA) {
832 return WTAP_OPEN_NOT_MINE; /* not a VWR file */
835 /* This is a vwr file */
836 vwr = (vwr_t *)g_malloc0(sizeof(vwr_t));
837 wth->priv = (void *)vwr;
839 vwr->FPGA_VERSION = fpgaVer;
840 /* set the local module options first */
841 setup_defaults(vwr, fpgaVer);
843 wth->snapshot_length = 0;
844 wth->subtype_read = vwr_read;
845 wth->subtype_seek_read = vwr_seek_read;
846 wth->file_tsprec = WTAP_TSPREC_USEC;
847 wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
849 if (fpgaVer == S2_W_FPGA || fpgaVer == S1_W_FPGA || fpgaVer == S3_W_FPGA)
850 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VWR_80211;
851 else if (fpgaVer == vVW510012_E_FPGA || fpgaVer == vVW510024_E_FPGA)
852 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VWR_ETH;
854 return WTAP_OPEN_MINE;
858 /* Read the next packet */
859 /* Note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
860 /* different types; some types, including frame record headers, are followed by */
861 /* variable-length data. */
862 /* A frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
863 /* frame, and a 64-byte statistics block trailer. */
864 /* The PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
866 static gboolean vwr_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
868 vwr_t *vwr = (vwr_t *)wth->priv;
869 int rec_size = 0, IS_TX, log_mode;
871 /* read the next frame record header in the capture file; if no more frames, return */
872 if (!vwr_read_rec_header(vwr, wth->fh, &rec_size, &IS_TX, &log_mode, err, err_info))
873 return FALSE; /* Read error or EOF */
876 * We're past the header; return the offset of the header, not of
877 * the data past the header.
879 *data_offset = (file_tell(wth->fh) - VW_RECORD_HEADER_LENGTH);
881 /* got a frame record; read and process it */
882 if (!vwr_process_rec_data(wth->fh, rec_size, &wth->phdr,
883 wth->frame_buffer, vwr, IS_TX, log_mode, err, err_info))
886 /* If the per-file encapsulation isn't known, set it to this packet's encapsulation. */
887 /* If it *is* known, and it isn't this packet's encapsulation, set it to */
888 /* WTAP_ENCAP_PER_PACKET, as this file doesn't have a single encapsulation for all */
889 /* packets in the file. */
890 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
891 wth->file_encap = wth->phdr.pkt_encap;
893 if (wth->file_encap != wth->phdr.pkt_encap)
894 wth->file_encap = WTAP_ENCAP_PER_PACKET;
900 /* read a random record in the middle of a file; the start of the record is @ seek_off */
902 static gboolean vwr_seek_read(wtap *wth, gint64 seek_off,
903 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
905 vwr_t *vwr = (vwr_t *)wth->priv;
906 int rec_size, IS_TX, log_mode;
908 /* first seek to the indicated record header */
909 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
912 /* read in the record header */
913 if (!vwr_read_rec_header(vwr, wth->random_fh, &rec_size, &IS_TX, &log_mode, err, err_info))
914 return FALSE; /* Read error or EOF */
916 return vwr_process_rec_data(wth->random_fh, rec_size, phdr, buf,
917 vwr, IS_TX, log_mode, err, err_info);
920 /* Scan down in the input capture file to find the next frame header. */
921 /* Decode and skip over all non-frame messages that are in the way. */
922 /* Return TRUE on success, FALSE on EOF or error. */
923 /* Also return the frame size in bytes and the "is transmitted frame" flag. */
925 static gboolean vwr_read_rec_header(vwr_t *vwr, FILE_T fh, int *rec_size, int *IS_TX, int *log_mode, int *err, gchar **err_info)
928 guint8 header[VW_RECORD_HEADER_LENGTH];
932 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
933 /* or if we run out of data. */
934 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
935 /* variable-length item, we read the variable length item out and discard it. */
936 /* If we find a frame, we return (with the header in the passed buffer). */
938 if (!wtap_read_bytes_or_eof(fh, header, VW_RECORD_HEADER_LENGTH, err, err_info))
941 /* Got a header; invoke decode-message function to parse and process it. */
942 /* If the function returns a length, then a frame or variable-length message */
943 /* follows the 16-byte message. */
944 /* If the variable length message is not a frame, simply skip over it. */
945 if ((f_len = decode_msg(vwr, header, &v_type, IS_TX, log_mode)) != 0) {
946 if (f_len > B_SIZE) {
947 *err = WTAP_ERR_BAD_FILE;
948 *err_info = g_strdup_printf("vwr: Invalid message record length %d", f_len);
951 else if (v_type != VT_FRAME) {
952 if (!wtap_read_bytes(fh, NULL, f_len, err, err_info))
963 /* Figure out the FPGA version (and also see whether this is a VWR file type. */
964 /* Return FPGA version if it's a known version, UNKNOWN_FPGA if it's not, */
965 /* and -1 on an I/O error. */
967 static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
969 guint8 *rec; /* local buffer (holds input record) */
970 guint8 header[VW_RECORD_HEADER_LENGTH];
973 guint8 *s_510006_ptr = NULL;
974 guint8 *s_510024_ptr = NULL;
975 guint8 *s_510012_ptr = NULL; /* stats pointers */
977 guint32 frame_type = 0;
979 guint16 data_length = 0;
980 guint16 fpga_version;
981 int valid_but_empty_file = -1;
983 filePos = file_tell(wth->fh);
985 *err = file_error(wth->fh, err_info);
990 rec = (guint8*)g_malloc(B_SIZE);
991 /* Got a frame record; see if it is vwr */
992 /* If we don't get it all, then declare an error, we can't process the frame. */
993 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
994 /* or if we run out of data. */
995 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
996 /* variable-length item, we read the variable length item out and discard it. */
997 /* If we find a frame, we return (with the header in the passed buffer). */
998 while (wtap_read_bytes(wth->fh, header, VW_RECORD_HEADER_LENGTH, err, err_info)) {
999 /* Got a header; invoke decode-message function to parse and process it. */
1000 /* If the function returns a length, then a frame or variable-length message */
1001 /* follows the 16-byte message. */
1002 /* If the variable length message is not a frame, simply skip over it. */
1003 if ((f_len = decode_msg(NULL, header, &v_type, NULL, NULL)) != 0) {
1004 if (f_len > B_SIZE) {
1006 /* Treat this here as an indication that the file probably */
1007 /* isn't a vwr file. */
1008 return UNKNOWN_FPGA;
1010 else if (v_type != VT_FRAME) {
1011 if (!wtap_read_bytes(wth->fh, NULL, f_len, err, err_info)) {
1015 else if (v_type == VT_CPMSG)
1016 valid_but_empty_file = 1;
1020 /* Got a frame record; read over entire record (frame + trailer) into a local buffer */
1021 /* If we don't get it all, assume this isn't a vwr file */
1022 if (!wtap_read_bytes(wth->fh, rec, rec_size, err, err_info)) {
1024 if (*err == WTAP_ERR_SHORT_READ)
1025 return UNKNOWN_FPGA; /* short read - not a vwr file */
1029 /* I'll grab the bytes where the Ethernet "octets" field should be and the bytes where */
1030 /* the 802.11 "octets" field should be. Then if I do rec_size - octets - */
1031 /* size_of_stats_block and it's 0, I can select the correct type. */
1032 /* octets + stats_len = rec_size only when octets have been incremented to nearest */
1033 /* number divisible by 4. */
1035 /* First check for series I WLAN since the check is more rigorous. */
1036 if (rec_size > v22_W_STATS_LEN) {
1037 s_510006_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to 510006 WLAN */
1040 data_length = pntoh16(&s_510006_ptr[v22_W_OCTET_OFF]);
1042 while (((data_length + i) % 4) != 0)
1045 frame_type = pntoh32(&s_510006_ptr[v22_W_FRAME_TYPE_OFF]);
1047 if (rec_size == (data_length + v22_W_STATS_LEN + i) && (frame_type & v22_W_IS_80211) == 0x1000000) {
1048 fpga_version = S1_W_FPGA;
1052 /* Next for the series I Ethernet */
1053 if ((rec_size > v22_E_STATS_LEN) && (fpga_version == 1000)) {
1054 s_510012_ptr = &(rec[rec_size - v22_E_STATS_LEN]); /* point to 510012 enet */
1056 data_length = pntoh16(&s_510012_ptr[v22_E_OCTET_OFF]);
1058 while (((data_length + i) % 4) != 0)
1061 if (rec_size == (data_length + v22_E_STATS_LEN + i))
1062 fpga_version = vVW510012_E_FPGA;
1066 /* Next the series II WLAN */
1067 if ((rec_size > vVW510021_W_STATS_TRAILER_LEN) && (fpga_version == 1000)) {
1070 if ((header[8] == 48) || (header[8] == 61) || (header[8] == 68))
1071 fpga_version = S3_W_FPGA;
1073 data_length = (256 * (rec[vVW510021_W_MSDU_LENGTH_OFF + 1] & 0x1f)) + rec[vVW510021_W_MSDU_LENGTH_OFF];
1076 while (((data_length + i) % 4) != 0)
1079 /*the 12 is from the 12 bytes of plcp header */
1080 if (rec_size == (data_length + vVW510021_W_STATS_TRAILER_LEN +vVW510021_W_AFTERHEADER_LEN+12+i))
1081 fpga_version = S2_W_FPGA;
1085 /* Finally the Series II Ethernet */
1086 if ((rec_size > vVW510024_E_STATS_LEN) && (fpga_version == 1000)) {
1087 s_510024_ptr = &(rec[rec_size - vVW510024_E_STATS_LEN]); /* point to 510024 ENET */
1088 data_length = pntoh16(&s_510024_ptr[vVW510024_E_MSDU_LENGTH_OFF]);
1091 while (((data_length + i) % 4) != 0)
1094 if (rec_size == (data_length + vVW510024_E_STATS_LEN + i))
1095 fpga_version = vVW510024_E_FPGA;
1098 if (fpga_version != 1000)
1100 /* reset the file position offset */
1101 if (file_seek (wth->fh, filePos, SEEK_SET, err) == -1) {
1106 /* We found an FPGA that works */
1108 return fpga_version;
1114 /* Is this a valid but empty file? If so, claim it's the S3_W_FPGA FPGA. */
1115 if (valid_but_empty_file > 0) {
1120 if (*err == WTAP_ERR_SHORT_READ) {
1122 return UNKNOWN_FPGA; /* short read - not a vwr file */
1132 /* Copy the actual packet data from the capture file into the target data block. */
1133 /* The packet is constructed as a 38-byte VeriWave metadata header plus the raw */
1136 static gboolean vwr_read_s1_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
1137 Buffer *buf, const guint8 *rec, int rec_size,
1138 int *err, gchar **err_info)
1141 int bytes_written = 0; /* bytes output to buf so far */
1142 const guint8 *s_ptr, *m_ptr; /* stats pointer */
1143 guint16 msdu_length, actual_octets; /* octets in frame */
1144 guint16 plcp_hdr_len; /* PLCP header length */
1146 guint8 m_type; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
1148 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1151 guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
1152 guint64 end_time; /* end time */
1153 guint32 info; /* INFO/ERRORS fields in stats blk */
1154 gint8 rssi; /* RSSI, signed 8-bit number */
1155 int f_tx; /* flag: if set, is a TX frame */
1156 guint8 rate_index; /* pre-HT only */
1157 guint16 vc_id, ht_len=0; /* VC ID, total ip length */
1158 guint flow_id; /* flow ID */
1159 guint32 d_time, errors; /* packet duration & errors */
1160 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1161 guint64 sig_ts; /* 32 LSBs of timestamp in signature */
1163 guint16 vw_flags; /* VeriWave-specific packet flags */
1166 * The record data must be large enough to hold the statistics trailer.
1168 if (rec_size < v22_W_STATS_LEN) {
1169 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1170 rec_size, v22_W_STATS_LEN);
1171 *err = WTAP_ERR_BAD_FILE;
1175 /* Calculate the start of the statistics block in the buffer */
1176 /* Also get a bunch of fields from the stats block */
1177 s_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to it */
1178 m_type = s_ptr[v22_W_MTYPE_OFF] & v22_E_MT_MASK;
1179 f_tx = !(s_ptr[v22_W_MTYPE_OFF] & v22_E_IS_RX);
1180 actual_octets = pntoh16(&s_ptr[v22_W_OCTET_OFF]);
1181 vc_id = pntoh16(&s_ptr[v22_W_VCID_OFF]) & v22_E_VCID_MASK;
1182 flow_seq = s_ptr[v22_W_FLOWSEQ_OFF];
1184 latency = (guint32)pcorey48tohll(&s_ptr[v22_W_LATVAL_OFF]);
1186 flow_id = pntoh16(&s_ptr[v22_W_FLOWID_OFF+1]); /* only 16 LSBs kept */
1187 errors = pntoh16(&s_ptr[v22_W_ERRORS_OFF]);
1189 info = pntoh16(&s_ptr[v22_W_INFO_OFF]);
1190 rssi = (s_ptr[v22_W_RSSI_OFF] & 0x80) ? (-1 * (s_ptr[v22_W_RSSI_OFF] & 0x7f)) : s_ptr[v22_W_RSSI_OFF];
1193 * Sanity check the octets field to determine if it's greater than
1194 * the packet data available in the record - i.e., the record size
1195 * minus the length of the statistics block.
1197 * Report an error if it is.
1199 if (actual_octets > rec_size - v22_W_STATS_LEN) {
1200 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1202 *err = WTAP_ERR_BAD_FILE;
1206 /* Decode OFDM or CCK PLCP header and determine rate and short preamble flag. */
1207 /* The SIGNAL byte is always the first byte of the PLCP header in the frame. */
1208 if (m_type == vwr->MT_OFDM)
1209 rate_index = get_ofdm_rate(rec);
1210 else if ((m_type == vwr->MT_CCKL) || (m_type == vwr->MT_CCKS))
1211 rate_index = get_cck_rate(rec);
1214 rflags = (m_type == vwr->MT_CCKS) ? FLAGS_SHORTPRE : 0;
1215 /* Calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK. */
1216 /* Note that the number of octets in the frame also varies depending on OFDM/CCK, */
1217 /* because the PLCP header is prepended to the actual MPDU. */
1218 plcp_hdr_len = (m_type == vwr->MT_OFDM) ? 4 : 6;
1219 if (actual_octets >= plcp_hdr_len)
1220 actual_octets -= plcp_hdr_len;
1222 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header)",
1223 actual_octets, plcp_hdr_len);
1224 *err = WTAP_ERR_BAD_FILE;
1227 m_ptr = &rec[plcp_hdr_len];
1228 msdu_length = actual_octets;
1231 * The MSDU length includes the FCS.
1233 * The packet data does *not* include the FCS - it's just 4 bytes
1234 * of junk - so we have to remove it.
1236 * We'll be stripping off an FCS (?), so make sure we have at
1237 * least 4 octets worth of FCS.
1239 if (actual_octets < 4) {
1240 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header and 4 bytes of FCS)",
1241 actual_octets, plcp_hdr_len);
1242 *err = WTAP_ERR_BAD_FILE;
1247 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1248 /* 64-bit times are "Corey-endian" */
1249 s_time = pcoreytohll(&s_ptr[v22_W_STARTT_OFF]);
1250 e_time = pcoreytohll(&s_ptr[v22_W_ENDT_OFF]);
1252 /* find the packet duration (difference between start and end times) */
1253 d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
1255 /* also convert the packet start time to seconds and microseconds */
1256 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1257 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1258 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1260 /* also convert the packet end time to seconds and microseconds */
1261 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1263 /* extract the 32 LSBs of the signature timestamp field from the data block*/
1264 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
1265 sig_off = find_signature(m_ptr, rec_size - 6, pay_off, flow_id, flow_seq);
1266 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - v22_W_STATS_LEN)))
1267 sig_ts = get_signature_ts(m_ptr, sig_off);
1272 * Fill up the per-packet header.
1274 * We include the length of the metadata headers in the packet lengths.
1276 * The maximum value of actual_octets is 8191, which, even after
1277 * adding the lengths of the metadata headers, is less than
1278 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1280 phdr->len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1281 phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1283 phdr->ts.secs = (time_t)s_sec;
1284 phdr->ts.nsecs = (int)(s_usec * 1000);
1285 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1287 phdr->rec_type = REC_TYPE_PACKET;
1288 phdr->presence_flags = WTAP_HAS_TS;
1290 ws_buffer_assure_space(buf, phdr->caplen);
1291 data_ptr = ws_buffer_start_ptr(buf);
1294 * Generate and copy out the common metadata headers,
1295 * set the port type to 0 (WLAN).
1297 * All values are copied out in little-endian byte order.
1299 /* 1st octet of record for port_type and command (command is 0, hence RX) */
1300 phtole8(&data_ptr[bytes_written], WLAN_PORT);
1302 /* 2nd octet of record for fpga version (0, hence pre-OCTO) */
1303 phtole8(&data_ptr[bytes_written], 0);
1306 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
1308 phtoles(&data_ptr[bytes_written], msdu_length);
1310 phtolel(&data_ptr[bytes_written], flow_id);
1312 phtoles(&data_ptr[bytes_written], vc_id);
1314 phtoles(&data_ptr[bytes_written], flow_seq);
1316 if (!f_tx && sig_ts != 0) {
1317 phtolel(&data_ptr[bytes_written], latency);
1319 phtolel(&data_ptr[bytes_written], 0);
1322 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
1324 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
1326 phtolell(&data_ptr[bytes_written], end_time);
1328 phtolel(&data_ptr[bytes_written], d_time);
1332 * Generate and copy out the WLAN metadata headers.
1334 * All values are copied out in little-endian byte order.
1336 phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
1338 phtoles(&data_ptr[bytes_written], rflags);
1340 if (m_type == vwr->MT_OFDM) {
1341 phtoles(&data_ptr[bytes_written], CHAN_OFDM);
1343 phtoles(&data_ptr[bytes_written], CHAN_CCK);
1346 phyRate = (guint16)(get_legacy_rate(rate_index) * 10);
1347 phtoles(&data_ptr[bytes_written], phyRate);
1349 data_ptr[bytes_written] = vVW510021_W_PLCP_LEGACY; /* pre-HT */
1351 data_ptr[bytes_written] = rate_index;
1353 data_ptr[bytes_written] = 1; /* pre-VHT, so NSS = 1 */
1355 data_ptr[bytes_written] = rssi;
1357 /* antennae b, c, d signal power */
1358 data_ptr[bytes_written] = 100;
1360 data_ptr[bytes_written] = 100;
1362 data_ptr[bytes_written] = 100;
1365 data_ptr[bytes_written] = 0;
1368 /* fill in the VeriWave flags field */
1371 vw_flags |= VW_FLAGS_TXF;
1372 if (errors & vwr->FCS_ERROR)
1373 vw_flags |= VW_FLAGS_FCSERR;
1374 if (!f_tx && (errors & vwr->CRYPTO_ERR))
1375 vw_flags |= VW_FLAGS_DCRERR;
1376 if (!f_tx && (errors & vwr->RETRY_ERR))
1377 vw_flags |= VW_FLAGS_RETRERR;
1378 if (info & vwr->WEPTYPE)
1379 vw_flags |= VW_FLAGS_IS_WEP;
1380 else if (info & vwr->TKIPTYPE)
1381 vw_flags |= VW_FLAGS_IS_TKIP;
1382 else if (info & vwr->CCMPTYPE)
1383 vw_flags |= VW_FLAGS_IS_CCMP;
1384 phtoles(&data_ptr[bytes_written], vw_flags);
1387 phtoles(&data_ptr[bytes_written], ht_len);
1389 phtoles(&data_ptr[bytes_written], info);
1391 phtolel(&data_ptr[bytes_written], errors);
1395 * Finally, copy the whole MAC frame to the packet buffer as-is.
1396 * This does not include the PLCP; the MPDU starts at 4 or 6
1397 * depending on OFDM/CCK.
1398 * This also does not include the last 4 bytes, as those don't
1399 * contain an FCS, they just contain junk.
1401 memcpy(&data_ptr[bytes_written], &rec[plcp_hdr_len], actual_octets);
1407 static gboolean vwr_read_s2_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
1408 Buffer *buf, const guint8 *rec, int rec_size,
1409 int IS_TX, int *err, gchar **err_info)
1412 int bytes_written = 0; /* bytes output to buf so far */
1413 const guint8 *s_start_ptr,*s_trail_ptr, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
1414 guint32 msdu_length, actual_octets; /* octets in frame */
1415 guint8 l1p_1, l1p_2, plcp_type, rate_mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
1417 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1419 guint64 latency = LL_ZERO;
1420 guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
1421 guint64 end_time; /* end time */
1422 guint16 info; /* INFO/ERRORS fields in stats blk */
1424 gint8 rssi[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1425 int f_tx; /* flag: if set, is a TX frame */
1426 guint16 vc_id, ht_len=0; /* VC ID , total ip length*/
1427 guint32 flow_id, d_time; /* flow ID, packet duration*/
1428 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1429 guint64 sig_ts, tsid; /* 32 LSBs of timestamp in signature */
1430 guint16 chanflags = 0; /* channel flags for WLAN metadata header */
1431 guint16 radioflags = 0; /* flags for WLAN metadata header */
1432 guint64 delta_b; /* Used for calculating latency */
1435 guint16 vw_flags; /* VeriWave-specific packet flags */
1438 * The record data must be large enough to hold the statistics header,
1439 * the PLCP, and the statistics trailer.
1441 if ((guint)rec_size < vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1442 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1444 vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1445 *err = WTAP_ERR_BAD_FILE;
1449 /* Calculate the start of the statistics blocks in the buffer */
1450 /* Also get a bunch of fields from the stats blocks */
1451 s_start_ptr = &(rec[0]); /* point to stats header */
1452 s_trail_ptr = &(rec[rec_size - vVW510021_W_STATS_TRAILER_LEN]); /* point to stats trailer */
1454 l1p_1 = s_start_ptr[vVW510021_W_L1P_1_OFF];
1455 l1p_2 = s_start_ptr[vVW510021_W_L1P_2_OFF];
1456 plcp_type = vVW510021_W_S2_PLCP_TYPE(l1p_2);
1457 /* we do the range checks at the end before copying the values
1458 into the wtap header */
1459 msdu_length = ((s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF+1] & 0x1f) << 8)
1460 + s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF];
1462 vc_id = pntoh16(&s_start_ptr[vVW510021_W_VCID_OFF]);
1465 rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
1466 -1 * (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f) :
1467 s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f;
1471 rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
1472 (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF]- 256) :
1473 s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF];
1479 plcp_ptr = &(rec[8]);
1481 actual_octets = msdu_length;
1484 * Sanity check the octets field to determine if it's greater than
1485 * the packet data available in the record - i.e., the record size
1486 * minus the sum of (length of statistics header + PLCP) and
1487 * (length of statistics trailer).
1489 * Report an error if it is.
1491 if (actual_octets > rec_size - (vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN)) {
1492 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1494 *err = WTAP_ERR_BAD_FILE;
1499 flow_seq = s_trail_ptr[vVW510021_W_FLOWSEQ_OFF];
1501 latency = 0x00000000; /* clear latency */
1502 flow_id = pntoh24(&s_trail_ptr[vVW510021_W_FLOWID_OFF]); /* all 24 bits valid */
1503 /* For tx latency is duration, for rx latency is timestamp */
1504 /* Get 48-bit latency value */
1505 tsid = pcorey48tohll(&s_trail_ptr[vVW510021_W_LATVAL_OFF]);
1507 errors = pntoh32(&s_trail_ptr[vVW510021_W_ERRORS_OFF]);
1508 info = pntoh16(&s_trail_ptr[vVW510021_W_INFO_OFF]);
1509 if ((info & v22_W_AGGREGATE_FLAGS) != 0)
1510 /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
1511 ht_len = pletoh16(&s_start_ptr[vwr->PLCP_LENGTH_OFF]);
1514 /* decode OFDM or CCK PLCP header and determine rate and short preamble flag */
1515 /* the SIGNAL byte is always the first byte of the PLCP header in the frame */
1518 case vVW510021_W_PLCP_LEGACY:
1520 * From IEEE Std 802.11-2012:
1522 * According to section 17.2.2 "PPDU format", the PLCP header
1523 * for the High Rate DSSS PHY (11b) has a SIGNAL field that's
1524 * 8 bits, followed by a SERVICE field that's 8 bits, followed
1525 * by a LENGTH field that's 16 bits, followed by a CRC field
1526 * that's 16 bits. The PSDU follows it. Section 17.2.3 "PPDU
1527 * field definitions" describes those fields.
1529 * According to sections 18.3.2 "PLCP frame format" and 18.3.4
1530 * "SIGNAL field", the PLCP for the OFDM PHY (11a) has a SIGNAL
1531 * field that's 24 bits, followed by a service field that's
1532 * 16 bits, followed by the PSDU. Section 18.3.5.2 "SERVICE
1533 * field" describes the SERVICE field.
1535 * According to section 19.3.2 "PPDU format", the frames for the
1536 * Extended Rate PHY (11g) either extend the 11b format, using
1537 * additional bits in the SERVICE field, or extend the 11a
1540 rate_mcs_index = vVW510021_W_S2_RATE_INDEX(l1p_1);
1541 if (rate_mcs_index < 4) {
1542 chanflags |= CHAN_CCK;
1545 chanflags |= CHAN_OFDM;
1547 rate = get_legacy_rate(rate_mcs_index);
1551 case vVW510021_W_PLCP_MIXED:
1553 * According to section 20.3.2 "PPDU format", the HT-mixed
1554 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
1555 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
1556 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
1559 * This means that the first octet of HT-SIG is at
1560 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
1562 * 0x80 is the CBW 20/40 bit of HT-SIG.
1564 /* set the appropriate flags to indicate HT mode and CB */
1565 rate_mcs_index = vVW510021_W_S2_MCS_INDEX_HT(l1p_1);
1566 radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[3] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
1567 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1568 chanflags |= CHAN_OFDM;
1569 nss = (rate_mcs_index < MAX_HT_MCS) ? nss_for_mcs[rate_mcs_index] : 0;
1570 rate = get_ht_rate(rate_mcs_index, radioflags);
1573 case vVW510021_W_PLCP_GREENFIELD:
1575 * According to section 20.3.2 "PPDU format", the HT-greenfield
1576 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
1579 * This means that the first octet of HT-SIG is at
1580 * plcp_ptr[0], as there's no L-SIG field to skip.
1582 * 0x80 is the CBW 20/40 bit of HT-SIG.
1584 /* set the appropriate flags to indicate HT mode and CB */
1585 rate_mcs_index = vVW510021_W_S2_MCS_INDEX_HT(l1p_1);
1586 radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[0] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
1587 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1588 chanflags |= CHAN_OFDM;
1589 nss = (rate_mcs_index < MAX_HT_MCS) ? nss_for_mcs[rate_mcs_index] : 0;
1590 rate = get_ht_rate(rate_mcs_index, radioflags);
1593 case vVW510021_W_PLCP_VHT_MIXED:
1595 * According to section 22.3.2 "VHT PPDU format" of IEEE Std
1596 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
1597 * (L-SIG), which looks like an 11a SIGNAL field, followed by
1598 * a VHT Signal A field (VHT-SIG-A) described in section
1599 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
1600 * between it and a VHT Signal B field (VHT-SIG-B) described
1601 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
1605 guint8 SBW = vVW510021_W_BANDWIDTH_VHT(l1p_2);
1606 rate_mcs_index = vVW510021_W_S2_MCS_INDEX_VHT(l1p_1);
1607 radioflags |= FLAGS_CHAN_VHT | ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1608 chanflags |= CHAN_OFDM;
1610 radioflags |= FLAGS_CHAN_40MHZ;
1612 radioflags |= FLAGS_CHAN_80MHZ;
1613 nss = vVW510021_W_S2_NSS_VHT(l1p_1);
1614 rate = get_vht_rate(rate_mcs_index, radioflags, nss);
1626 * The MSDU length includes the FCS.
1628 * The packet data does *not* include the FCS - it's just 4 bytes
1629 * of junk - so we have to remove it.
1631 * We'll be stripping off an FCS (?), so make sure we have at
1632 * least 4 octets worth of FCS.
1634 if (actual_octets < 4) {
1635 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
1637 *err = WTAP_ERR_BAD_FILE;
1640 if (actual_octets > 4) {
1644 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1645 /* 64-bit times are "Corey-endian" */
1646 s_time = pcoreytohll(&s_trail_ptr[vVW510021_W_STARTT_OFF]);
1647 e_time = pcoreytohll(&s_trail_ptr[vVW510021_W_ENDT_OFF]);
1649 /* find the packet duration (difference between start and end times) */
1650 d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
1652 /* also convert the packet start time to seconds and microseconds */
1653 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1654 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1655 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1657 /* also convert the packet end time to seconds and microseconds */
1658 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1660 /* extract the 32 LSBs of the signature timestamp field */
1661 m_ptr = &(rec[8+12]);
1662 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
1663 sig_off = find_signature(m_ptr, rec_size - 20, pay_off, flow_id, flow_seq);
1664 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - vVW510021_W_STATS_TRAILER_LEN)))
1665 sig_ts = get_signature_ts(m_ptr, sig_off);
1669 /* Set latency based on rx/tx and signature timestamp */
1671 if (tsid < s_time) {
1672 latency = s_time - tsid;
1674 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1675 /* we look for a large difference between l_time and s_time. */
1676 delta_b = tsid - s_time;
1677 if (delta_b > 0x10000000)
1685 * Fill up the per-packet header.
1687 * We include the length of the metadata headers in the packet lengths.
1689 * The maximum value of actual_octets is 8191, which, even after
1690 * adding the lengths of the metadata headers, is less than
1691 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1693 phdr->len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1694 phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1696 phdr->ts.secs = (time_t)s_sec;
1697 phdr->ts.nsecs = (int)(s_usec * 1000);
1698 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1700 phdr->rec_type = REC_TYPE_PACKET;
1701 phdr->presence_flags = WTAP_HAS_TS;
1703 ws_buffer_assure_space(buf, phdr->caplen);
1704 data_ptr = ws_buffer_start_ptr(buf);
1707 * Generate and copy out the common metadata headers,
1708 * set the port type to 0 (WLAN).
1710 * All values are copied out in little-endian byte order.
1712 /*** msdu_length = msdu_length + 16; ***/
1713 /* 1st octet of record for port_type and command (command is 0, hence RX) */
1714 phtole8(&data_ptr[bytes_written], WLAN_PORT);
1716 /* 2nd octet of record for fpga version (0, hence pre-OCTO) */
1717 phtole8(&data_ptr[bytes_written], 0);
1720 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
1722 phtoles(&data_ptr[bytes_written], msdu_length);
1724 phtolel(&data_ptr[bytes_written], flow_id);
1726 phtoles(&data_ptr[bytes_written], vc_id);
1728 phtoles(&data_ptr[bytes_written], flow_seq);
1730 if (!f_tx && sig_ts != 0) {
1731 phtolel(&data_ptr[bytes_written], latency);
1733 phtolel(&data_ptr[bytes_written], 0);
1736 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
1738 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
1740 phtolell(&data_ptr[bytes_written], end_time);
1742 phtolel(&data_ptr[bytes_written], d_time);
1746 * Generate and copy out the WLAN metadata headers.
1748 * All values are copied out in little-endian byte order.
1750 phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
1752 if (info & vVW510021_W_IS_WEP)
1753 radioflags |= FLAGS_WEP;
1754 if (!(l1p_1 & vVW510021_W_IS_LONGPREAMBLE) && (plcp_type == vVW510021_W_PLCP_LEGACY))
1755 radioflags |= FLAGS_SHORTPRE;
1756 phtoles(&data_ptr[bytes_written], radioflags);
1758 phtoles(&data_ptr[bytes_written], chanflags);
1760 phyRate = (guint16)(rate * 10);
1761 phtoles(&data_ptr[bytes_written], phyRate);
1764 data_ptr[bytes_written] = plcp_type;
1767 data_ptr[bytes_written] = rate_mcs_index;
1770 data_ptr[bytes_written] = nss;
1772 data_ptr[bytes_written] = rssi[0];
1774 data_ptr[bytes_written] = rssi[1];
1776 data_ptr[bytes_written] = rssi[2];
1778 data_ptr[bytes_written] = rssi[3];
1781 data_ptr[bytes_written] = 0;
1784 /* fill in the VeriWave flags field */
1787 vw_flags |= VW_FLAGS_TXF;
1788 if (errors & 0x1f) /* If any error is flagged, then set the FCS error bit */
1789 vw_flags |= VW_FLAGS_FCSERR;
1790 if (!f_tx && (errors & vwr->CRYPTO_ERR))
1791 vw_flags |= VW_FLAGS_DCRERR;
1792 if (!f_tx && (errors & vwr->RETRY_ERR))
1793 vw_flags |= VW_FLAGS_RETRERR;
1794 if (info & vwr->WEPTYPE)
1795 vw_flags |= VW_FLAGS_IS_WEP;
1796 else if (info & vwr->TKIPTYPE)
1797 vw_flags |= VW_FLAGS_IS_TKIP;
1798 else if (info & vwr->CCMPTYPE)
1799 vw_flags |= VW_FLAGS_IS_CCMP;
1800 phtoles(&data_ptr[bytes_written], vw_flags);
1803 phtoles(&data_ptr[bytes_written], ht_len);
1805 phtoles(&data_ptr[bytes_written], info);
1807 phtolel(&data_ptr[bytes_written], errors);
1810 /* Finally, copy the whole MAC frame to the packet buffer as-is.
1811 * This does not include the stats header or the PLCP.
1812 * This also does not include the last 4 bytes, as those don't
1813 * contain an FCS, they just contain junk.
1815 memcpy(&data_ptr[bytes_written], &rec[vwr->MPDU_OFF], actual_octets);
1820 static gboolean vwr_read_s3_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
1821 Buffer *buf, const guint8 *rec, int rec_size,
1822 int IS_TX, int log_mode, int *err,
1826 int bytes_written = 0; /* bytes output to buf so far */
1828 int stats_offset = 0;
1829 const guint8 *s_start_ptr = NULL,*s_trail_ptr = NULL, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
1830 guint32 msdu_length = 0, actual_octets = 0; /* octets in frame */
1831 guint8 l1p_1 = 0,l1p_2 = 0, plcp_type, rate_mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
1832 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1834 guint64 latency = LL_ZERO;
1835 guint64 start_time = 0, s_sec = 0, s_usec = LL_ZERO; /* start time, sec + usec */
1836 guint64 end_time = 0; /* end time */
1837 guint16 info = 0; /* INFO/ERRORS fields in stats blk */
1839 gint8 info_2nd = 0,rssi[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1841 guint32 d_time = 0, flow_id = 0; /* packet duration, Flow Signature ID*/
1842 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1843 guint64 sig_ts = 0, tsid; /* 32 LSBs of timestamp in signature */
1844 guint64 delta_b; /* Used for calculating latency */
1845 guint8 L1InfoC,port_type,ver_fpga = 0;
1846 guint8 flow_seq =0,plcp_hdr_flag = 0,rf_id = 0; /* indicates plcp hdr info */
1847 const guint8 *rf_ptr = NULL;
1852 * The record data must be large enough to hold the statistics header,
1853 * the PLCP, and the statistics trailer.
1855 if (IS_TX == 3) { /*IS_TX =3, i.e., command type is RF Modified*/
1856 if ((guint)rec_size < OCTO_MODIFIED_RF_LEN) {
1857 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1859 OCTO_MODIFIED_RF_LEN);
1860 *err = WTAP_ERR_BAD_FILE;
1867 * Fill up the per-packet header.
1869 * We include the length of the metadata headers in the packet lengths.
1871 * OCTO_MODIFIED_RF_LEN + 1 is less than WTAP_MAX_PACKET_SIZE_STANDARD will
1872 * ever be, so we don't need to check it.
1874 phdr->len = OCTO_MODIFIED_RF_LEN + 1; /* 1st octet is reserved for detecting type of frame while displaying in wireshark */
1875 phdr->caplen = OCTO_MODIFIED_RF_LEN + 1;
1877 phdr->ts.secs = (time_t)s_sec;
1878 phdr->ts.nsecs = (int)(s_usec * 1000);
1879 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1881 phdr->rec_type = REC_TYPE_PACKET;
1882 phdr->presence_flags = WTAP_HAS_TS;
1884 ws_buffer_assure_space(buf, phdr->caplen);
1885 data_ptr = ws_buffer_start_ptr(buf);
1887 port_type = IS_TX << 4;
1893 /* Calculate the start of the statistics blocks in the buffer */
1894 /* Also get a bunch of fields from the stats blocks */
1895 /* 'stats_offset' variable is use to locate the exact offset.
1896 * When a RX frame contrains RF,
1897 * the postion of Stats, Layer 1-4, PLCP parameters are shifted to
1898 * + OCTO_RF_MOD_ACTUAL_LEN bytes
1900 if (IS_TX == 4) /*IS_TX =4, i.e., command type is RF-RX Modified*/
1902 stats_offset = OCTO_RF_MOD_ACTUAL_LEN;
1903 if ((guint)rec_size < stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1904 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1906 stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1907 *err = WTAP_ERR_BAD_FILE;
1916 if ((guint)rec_size < vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1917 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1919 vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1920 *err = WTAP_ERR_BAD_FILE;
1925 s_start_ptr = &(rec[stats_offset]); /* point to stats header */
1926 s_trail_ptr = &(rec[rec_size - vVW510021_W_STATS_TRAILER_LEN] ); /* point to stats trailer */
1928 l1p_1 = s_start_ptr[vVW510021_W_L1P_1_OFF];
1929 l1p_2 = s_start_ptr[vVW510021_W_L1P_2_OFF];
1931 plcp_type = vVW510021_W_S3_PLCP_TYPE(l1p_2);
1934 case vVW510021_W_PLCP_LEGACY:
1936 rate_mcs_index = vVW510021_W_S3_RATE_INDEX(l1p_1);
1940 case vVW510021_W_PLCP_MIXED:
1941 case vVW510021_W_PLCP_GREENFIELD:
1942 rate_mcs_index = vVW510021_W_S3_MCS_INDEX_HT(l1p_1);
1943 nss = (rate_mcs_index < MAX_HT_MCS) ? nss_for_mcs[rate_mcs_index] : 0;
1946 case vVW510021_W_PLCP_VHT_MIXED:
1947 rate_mcs_index = vVW510021_W_S3_MCS_INDEX_VHT(l1p_1);
1948 nss = vVW510021_W_S3_NSS_VHT(l1p_1);
1959 for (i = 0; i < 4; i++)
1963 rssi[i] = (s_start_ptr[4+i] & 0x80) ? -1 * (s_start_ptr[4+i] & 0x7f) : s_start_ptr[4+i] & 0x7f;
1967 rssi[i] = (s_start_ptr[4+i] >= 128) ? (s_start_ptr[4+i] - 256) : s_start_ptr[4+i];
1971 if (IS_TX == 0 || IS_TX == 4){
1972 L1InfoC = s_start_ptr[8];
1975 msdu_length = pntoh24(&s_start_ptr[9]);
1977 /*** 16 bytes of PLCP header + 1 byte of L1P for user position ***/
1978 plcp_ptr = &(rec[stats_offset+16]);
1980 /*** Add the PLCP length for S3_W_FPGA version VHT frames for Beamforming decode ***/
1981 if (log_mode == 3) {
1982 frame_size = rec_size - 80 - stats_offset;
1983 if (frame_size > ((int) msdu_length))
1984 actual_octets = msdu_length;
1986 actual_octets = frame_size;
1990 actual_octets = msdu_length;
1993 * Sanity check the octets field to determine if it's greater than
1994 * the packet data available in the record - i.e., the record size
1995 * minus the sum of (length of statistics header + PLCP) and
1996 * (length of statistics trailer).
1998 * Report an error if it is.
2000 if (actual_octets > rec_size - (stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN)) {
2001 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
2003 *err = WTAP_ERR_BAD_FILE;
2007 flow_seq = s_trail_ptr[vVW510021_W_FLOWSEQ_OFF];
2009 latency = 0x00000000; /* clear latency */
2010 flow_id = pntoh24(&s_trail_ptr[vVW510021_W_FLOWID_OFF]); /* all 24 bits valid */
2011 /* For tx latency is duration, for rx latency is timestamp */
2012 /* Get 48-bit latency value */
2013 tsid = pcorey48tohll(&s_trail_ptr[vVW510021_W_LATVAL_OFF]);
2015 errors = pntoh32(&s_trail_ptr[vVW510021_W_ERRORS_OFF]);
2016 info = pntoh16(&s_trail_ptr[vVW510021_W_INFO_OFF]);
2018 if (IS_TX == 0 || IS_TX == 4)
2019 info_2nd = s_trail_ptr[41];
2021 /*** Calculate Data rate based on
2022 * PLCP type, MCS index and number of spatial stream
2023 * radioflags is temporarily calculated, which is used in
2024 * get_ht_rate() and get_vht_rate().
2028 case vVW510021_W_PLCP_LEGACY:
2029 rate = get_legacy_rate(rate_mcs_index);
2032 case vVW510021_W_PLCP_MIXED:
2034 * According to section 20.3.2 "PPDU format", the HT-mixed
2035 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
2036 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
2037 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
2040 * This means that the first octet of HT-SIG is at
2041 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
2043 * 0x80 is the CBW 20/40 bit of HT-SIG.
2046 /* set the appropriate flags to indicate HT mode and CB */
2047 guint16 radioflags = FLAGS_CHAN_HT | ((plcp_ptr[3] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
2048 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
2049 rate = get_ht_rate(rate_mcs_index, radioflags);
2053 case vVW510021_W_PLCP_GREENFIELD:
2055 * According to section 20.3.2 "PPDU format", the HT-greenfield
2056 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
2059 * This means that the first octet of HT-SIG is at
2060 * plcp_ptr[0], as there's no L-SIG field to skip.
2062 * 0x80 is the CBW 20/40 bit of HT-SIG.
2065 /* set the appropriate flags to indicate HT mode and CB */
2066 guint16 radioflags = FLAGS_CHAN_HT | ((plcp_ptr[0] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
2067 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
2068 rate = get_ht_rate(rate_mcs_index, radioflags);
2072 case vVW510021_W_PLCP_VHT_MIXED:
2074 * According to section 22.3.2 "VHT PPDU format" of IEEE Std
2075 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
2076 * (L-SIG), which looks like an 11a SIGNAL field, followed by
2077 * a VHT Signal A field (VHT-SIG-A) described in section
2078 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
2079 * between it and a VHT Signal B field (VHT-SIG-B) described
2080 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
2084 guint8 SBW = vVW510021_W_BANDWIDTH_VHT(l1p_2);
2085 guint16 radioflags = FLAGS_CHAN_VHT | ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
2087 radioflags |= FLAGS_CHAN_40MHZ;
2089 radioflags |= FLAGS_CHAN_80MHZ;
2090 rate = get_vht_rate(rate_mcs_index, radioflags, nss);
2098 phyRate = (guint16)(rate * 10);
2099 /* Calculation of Data rate ends*/
2101 /* 'ver_fpga' is the 2nd Octet of each frame.
2102 * msb/lsb nibble indicates log mode/fpga version respectively.
2103 * where log mode = 0 is normal capture and 1 is reduced capture,
2104 * lsb nibble is set to 1 always as this function is applicable for only FPGA version >= 48
2106 if (log_mode == 3) {
2108 * The MSDU length includes the FCS.
2110 * The packet data does *not* include the FCS - it's just 4 bytes
2111 * of junk - so we have to remove it.
2113 * We'll be stripping off an FCS (?), so make sure we have at
2114 * least 4 octets worth of FCS.
2116 * XXX - is the FCS actually present here, as it appears to be
2117 * if log_mode isn't 3?
2119 if (actual_octets < 4) {
2120 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
2122 *err = WTAP_ERR_BAD_FILE;
2125 if (actual_octets > 4 && (frame_size >= (int) msdu_length))
2133 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
2134 /* 64-bit times are "Corey-endian" */
2135 s_time = pcoreytohll(&s_trail_ptr[vVW510021_W_STARTT_OFF]);
2136 e_time = pcoreytohll(&s_trail_ptr[vVW510021_W_ENDT_OFF]);
2138 /* find the packet duration (difference between start and end times) */
2139 d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
2141 /* also convert the packet start time to seconds and microseconds */
2142 start_time = s_time / NS_IN_US; /* convert to microseconds first */
2143 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
2144 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
2146 /* also convert the packet end time to seconds and microseconds */
2147 end_time = e_time / NS_IN_US; /* convert to microseconds first */
2149 /* extract the 32 LSBs of the signature timestamp field */
2150 m_ptr = &(rec[stats_offset+8+12]);
2151 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
2152 sig_off = find_signature(m_ptr, rec_size - 20, pay_off, flow_id, flow_seq);
2153 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - vVW510021_W_STATS_TRAILER_LEN)))
2154 sig_ts = get_signature_ts(m_ptr, sig_off);
2158 /* Set latency based on rx/tx and signature timestamp */
2159 if (IS_TX == 0 || IS_TX == 4) {
2160 if (tsid < s_time) {
2161 latency = s_time - tsid;
2163 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
2164 /* we look for a large difference between l_time and s_time. */
2165 delta_b = tsid - s_time;
2166 if (delta_b > 0x10000000)
2173 port_type = IS_TX << 4;
2176 * Fill up the per-packet header.
2178 * We include the length of the metadata headers in the packet lengths.
2181 phdr->len = OCTO_MODIFIED_RF_LEN + OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2182 phdr->caplen = OCTO_MODIFIED_RF_LEN + OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2184 phdr->len = OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2185 phdr->caplen = OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2187 if (phdr->caplen > WTAP_MAX_PACKET_SIZE_STANDARD) {
2189 * Probably a corrupt capture file; return an error,
2190 * so that our caller doesn't blow up trying to allocate
2191 * space for an immensely-large packet.
2193 *err_info = g_strdup_printf("vwr: File has %u-byte packet, bigger than maximum of %u",
2194 phdr->caplen, WTAP_MAX_PACKET_SIZE_STANDARD);
2195 *err = WTAP_ERR_BAD_FILE;
2199 phdr->ts.secs = (time_t)s_sec;
2200 phdr->ts.nsecs = (int)(s_usec * 1000);
2201 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
2203 phdr->rec_type = REC_TYPE_PACKET;
2204 phdr->presence_flags = WTAP_HAS_TS;
2206 ws_buffer_assure_space(buf, phdr->caplen);
2207 data_ptr = ws_buffer_start_ptr(buf);
2211 * Generate and copy out the common metadata headers,
2212 * set the port type to port_type (XXX).
2214 * All values are copied out in little-endian byte order.
2216 /*** msdu_length = msdu_length + 16; ***/
2218 /* 1st octet of record for port_type and other crud */
2219 phtole8(&data_ptr[bytes_written], port_type);
2223 phtole8(&data_ptr[bytes_written], ver_fpga); /* 2nd octet of record for FPGA version*/
2226 phtoles(&data_ptr[bytes_written], OCTO_TIMESTAMP_FIELDS_LEN); /* it_len */
2229 /*** Time Collapsible header started***/
2230 if (IS_TX == 1 && sig_ts != 0) {
2231 phtolel(&data_ptr[bytes_written], latency);
2233 phtolel(&data_ptr[bytes_written], 0);
2236 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
2238 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
2240 phtolell(&data_ptr[bytes_written], end_time);
2242 phtolel(&data_ptr[bytes_written], d_time);
2244 /*** Time Collapsible header ends ***/
2247 /*** RF Collapsable header starts***/
2248 if (IS_TX == 3 || IS_TX == 4) {
2249 phtole8(&data_ptr[bytes_written], rf_id);
2251 data_ptr[bytes_written] = 0;
2253 data_ptr[bytes_written] = 0;
2255 data_ptr[bytes_written] = 0;
2258 /*** NOISE for all 4 Ports ***/
2259 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2261 if (pntoh16(&rf_ptr[RF_PORT_1_NOISE_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2262 phtoles(&data_ptr[bytes_written], 0);
2265 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_NOISE_OFF+i*RF_INTER_PORT_GAP_OFF];
2267 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_NOISE_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2272 /*** SNR for all 4 Ports ***/
2273 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2275 if (pntoh16(&rf_ptr[RF_PORT_1_SNR_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2276 phtoles(&data_ptr[bytes_written], 0);
2279 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_SNR_OFF+i*RF_INTER_PORT_GAP_OFF];
2281 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_SNR_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2286 /*** PFE for all 4 Ports ***/
2287 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2289 if (pntoh16(&rf_ptr[RF_PORT_1_PFE_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2290 phtoles(&data_ptr[bytes_written], 0);
2293 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_PFE_OFF+i*RF_INTER_PORT_GAP_OFF];
2295 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_PFE_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2300 /*** EVM SIG Data for all 4 Ports ***/
2301 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2303 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SD_SIG_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2304 phtoles(&data_ptr[bytes_written], 0);
2307 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_SIG_OFF+i*RF_INTER_PORT_GAP_OFF];
2309 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_SIG_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2314 /*** EVM SIG PILOT for all 4 Ports ***/
2315 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2317 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SP_SIG_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2318 phtoles(&data_ptr[bytes_written], 0);
2321 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_SIG_OFF+i*RF_INTER_PORT_GAP_OFF];
2323 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_SIG_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2328 /*** EVM Data Data for all 4 Ports ***/
2329 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2331 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SD_DATA_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2332 phtoles(&data_ptr[bytes_written], 0);
2335 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_DATA_OFF+i*RF_INTER_PORT_GAP_OFF];
2337 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_DATA_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2342 /*** EVM Data PILOT for all 4 Ports ***/
2343 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2345 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SP_DATA_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2346 phtoles(&data_ptr[bytes_written], 0);
2349 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_DATA_OFF+i*RF_INTER_PORT_GAP_OFF];
2351 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_DATA_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2356 /*** EVM WORST SYMBOL for all 4 Ports ***/
2357 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2359 if (pntoh16(&rf_ptr[RF_PORT_1_DSYMBOL_IDX_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2360 phtoles(&data_ptr[bytes_written], 0);
2363 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_DSYMBOL_IDX_OFF+i*RF_INTER_PORT_GAP_OFF];
2365 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_DSYMBOL_IDX_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2370 /*** CONTEXT_P for all 4 Ports ***/
2371 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2373 if (pntoh16(&rf_ptr[RF_PORT_1_CONTEXT_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2374 phtoles(&data_ptr[bytes_written], 0);
2377 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_CONTEXT_OFF+i*RF_INTER_PORT_GAP_OFF];
2379 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_CONTEXT_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2384 /*** FOR rest 24 RF data bytes are commented for future use ***/
2386 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2388 if (pntoh16(&rf_ptr[20+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2389 phtoles(&data_ptr[bytes_written], 0);
2392 data_ptr[bytes_written] = rf_ptr[20+i*RF_INTER_PORT_GAP_OFF];
2394 data_ptr[bytes_written] = rf_ptr[21+i*RF_INTER_PORT_GAP_OFF];
2398 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2400 if (pntoh16(&rf_ptr[24+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2401 phtoles(&data_ptr[bytes_written], 0);
2404 data_ptr[bytes_written] = rf_ptr[24+i*RF_INTER_PORT_GAP_OFF];
2406 data_ptr[bytes_written] = rf_ptr[25+i*RF_INTER_PORT_GAP_OFF];
2410 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2412 if (pntoh16(&rf_ptr[26+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2413 phtoles(&data_ptr[bytes_written], 0);
2416 data_ptr[bytes_written] = rf_ptr[26+i*RF_INTER_PORT_GAP_OFF];
2418 data_ptr[bytes_written] = rf_ptr[27+i*RF_INTER_PORT_GAP_OFF];
2424 /*** RF Collapsable header ends***/
2428 * Generate and copy out the WLAN metadata headers.
2430 * All values are copied out in little-endian byte order.
2432 phtoles(&data_ptr[bytes_written], OCTO_LAYER1TO4_LEN);
2435 /*** Layer-1 Collapsible header started***/
2436 data_ptr[bytes_written] = l1p_1;
2439 data_ptr[bytes_written] = (nss << 4) | IS_TX;
2442 phtoles(&data_ptr[bytes_written], phyRate); /* To dosplay Data rate based on the PLCP type & MCS*/
2445 data_ptr[bytes_written] = l1p_2;
2448 data_ptr[bytes_written] = rssi[0];
2450 data_ptr[bytes_written] = rssi[1];
2452 data_ptr[bytes_written] = rssi[2];
2454 data_ptr[bytes_written] = rssi[3];
2457 /* padding may not be required for S3_W*/
2459 data_ptr[bytes_written] = s_start_ptr[2]; /*** For Signal Bandwidth Mask ***/
2461 data_ptr[bytes_written] = s_start_ptr[3]; /*** For Antenna Port Energy Detect and MU_MASK ***/
2464 if (plcp_hdr_flag == 1 && (IS_TX == 0 || IS_TX == 4)) {
2465 data_ptr[bytes_written] = L1InfoC; /*** For Other plcp type = VHT ***/
2467 data_ptr[bytes_written] = 0; /*** For Other plcp type, this offset is set to 0***/
2471 phtoles(&data_ptr[bytes_written], msdu_length);
2473 /*** Layer-1 Collapsible header Ends ***/
2475 /*** PLCP Collapsible header Starts ***/
2476 memcpy(&data_ptr[bytes_written], &rec[stats_offset+16], 16);
2477 bytes_written += 16;
2478 /*** PLCP Collapsible header Ends ***/
2480 /*** Layer 2-4 Collapsible header Starts ***/
2482 phtolel(&data_ptr[bytes_written], pntoh32(&s_start_ptr[12])); /*** This 4 bytes includes BM,BV,CV,BSSID and ClientID ***/
2484 phtoles(&data_ptr[bytes_written], pntoh16(&s_trail_ptr[20])); /*** 2 bytes includes FV,QT,HT,L4V,TID and WLAN type ***/
2486 data_ptr[bytes_written] = flow_seq;
2488 phtole24(&data_ptr[bytes_written], flow_id);
2490 phtoles(&data_ptr[bytes_written], pntoh16(&s_trail_ptr[28])); /*** 2 bytes for Layer 4 ID ***/
2492 phtolel(&data_ptr[bytes_written], pntoh32(&s_trail_ptr[24])); /*** 4 bytes for Payload Decode ***/
2495 /*** Incase of RX, Info has 3 bytes of data, whereas for TX, 2 bytes ***/
2496 if (IS_TX == 0 || IS_TX == 4) {
2497 phtoles(&data_ptr[bytes_written], info);
2499 data_ptr[bytes_written] = info_2nd;
2503 phtoles(&data_ptr[bytes_written], info);
2505 data_ptr[bytes_written] = 0;
2509 phtolel(&data_ptr[bytes_written], errors);
2511 /*** Layer 2-4 Collapsible header Ends ***/
2513 /* Finally, copy the whole MAC frame to the packet buffer as-is.
2514 * This does not include the stats header or the PLCP.
2515 * This also does not include the last 4 bytes, as those don't
2516 * contain an FCS, they just contain junk.
2518 memcpy(&data_ptr[bytes_written], &rec[stats_offset+(vwr->MPDU_OFF)], actual_octets);
2524 /* read an Ethernet packet */
2525 /* Copy the actual packet data from the capture file into the target data block. */
2526 /* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
2528 static gboolean vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
2529 Buffer *buf, const guint8 *rec,
2530 int rec_size, int IS_TX, int *err,
2534 int bytes_written = 0; /* bytes output to buf so far */
2535 const guint8 *s_ptr, *m_ptr; /* stats and MPDU pointers */
2536 guint16 msdu_length, actual_octets; /* octets in frame */
2537 guint flow_seq; /* seqnum */
2538 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
2540 guint32 latency = 0;
2541 guint64 start_time, s_sec = LL_ZERO, s_usec = LL_ZERO; /* start time, sec + usec */
2542 guint64 end_time; /* end time */
2544 guint16 info, validityBits; /* INFO/ERRORS fields in stats */
2546 guint16 vc_id; /* VC ID, total (incl of aggregates) */
2547 guint32 flow_id, d_time; /* packet duration */
2548 int f_flow; /* flags: flow valid */
2549 guint32 frame_type; /* frame type field */
2550 int mac_len, sig_off, pay_off; /* MAC header len, signature offset */
2551 /* XXX - the code here fetched tsid, but never used it! */
2552 guint64 sig_ts/*, tsid*/; /* 32 LSBs of timestamp in signature */
2553 guint64 delta_b; /* Used for calculating latency */
2554 guint16 vw_flags; /* VeriWave-specific packet flags */
2556 if ((guint)rec_size < vwr->STATS_LEN) {
2557 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)", rec_size, vwr->STATS_LEN);
2558 *err = WTAP_ERR_BAD_FILE;
2562 /* Calculate the start of the statistics block in the buffer. */
2563 /* Also get a bunch of fields from the stats block. */
2564 m_ptr = &(rec[0]); /* point to the data block */
2565 s_ptr = &(rec[rec_size - vwr->STATS_LEN]); /* point to the stats block */
2567 msdu_length = pntoh16(&s_ptr[vwr->OCTET_OFF]);
2568 actual_octets = msdu_length;
2571 * Sanity check the octets field to determine if it's greater than
2572 * the packet data available in the record - i.e., the record size
2573 * minus the length of the statistics block.
2575 * Report an error if it is.
2577 if (actual_octets > rec_size - vwr->STATS_LEN) {
2578 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
2580 *err = WTAP_ERR_BAD_FILE;
2584 vc_id = pntoh16(&s_ptr[vwr->VCID_OFF]) & vwr->VCID_MASK;
2585 flow_seq = s_ptr[vwr->FLOWSEQ_OFF];
2586 frame_type = pntoh32(&s_ptr[vwr->FRAME_TYPE_OFF]);
2588 if (vwr->FPGA_VERSION == vVW510024_E_FPGA) {
2589 validityBits = pntoh16(&s_ptr[vwr->VALID_OFF]);
2590 f_flow = validityBits & vwr->FLOW_VALID;
2592 mac_len = (validityBits & vwr->IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
2595 errors = pntoh16(&s_ptr[vwr->ERRORS_OFF]);
2598 f_flow = s_ptr[vwr->VALID_OFF] & vwr->FLOW_VALID;
2599 mac_len = (frame_type & vwr->IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
2601 /* for older fpga errors is only represented by 16 bits) */
2602 errors = pntoh16(&s_ptr[vwr->ERRORS_OFF]);
2605 info = pntoh16(&s_ptr[vwr->INFO_OFF]);
2607 flow_id = pntoh24(&s_ptr[vwr->FLOWID_OFF]);
2610 /* For tx latency is duration, for rx latency is timestamp. */
2611 /* Get 64-bit latency value. */
2612 tsid = pcorey48tohll(&s_ptr[vwr->LATVAL_OFF]);
2615 l4id = pntoh16(&s_ptr[vwr->L4ID_OFF]);
2618 * The MSDU length includes the FCS.
2620 * The packet data does *not* include the FCS - it's just 4 bytes
2621 * of junk - so we have to remove it.
2623 * We'll be stripping off an FCS (?), so make sure we have at
2624 * least 4 octets worth of FCS.
2626 if (actual_octets < 4) {
2627 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
2629 *err = WTAP_ERR_BAD_FILE;
2634 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
2635 /* 64-bit times are "Corey-endian" */
2636 s_time = pcoreytohll(&s_ptr[vwr->STARTT_OFF]);
2637 e_time = pcoreytohll(&s_ptr[vwr->ENDT_OFF]);
2639 /* find the packet duration (difference between start and end times) */
2640 d_time = (guint32)((e_time - s_time)); /* find diff, leaving in nsec for Ethernet */
2642 /* also convert the packet start time to seconds and microseconds */
2643 start_time = s_time / NS_IN_US; /* convert to microseconds first */
2644 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
2645 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
2647 /* also convert the packet end time to seconds and microseconds */
2648 end_time = e_time / NS_IN_US; /* convert to microseconds first */
2650 if (frame_type & vwr->IS_TCP) /* signature offset for TCP frame */
2652 pay_off = mac_len + 40;
2654 else if (frame_type & vwr->IS_UDP) /* signature offset for UDP frame */
2656 pay_off = mac_len + 28;
2658 else if (frame_type & vwr->IS_ICMP) /* signature offset for ICMP frame */
2660 pay_off = mac_len + 24;
2662 else if (frame_type & vwr->IS_IGMP) /* signature offset for IGMPv2 frame */
2664 pay_off = mac_len + 28;
2666 else /* signature offset for raw IP frame */
2668 pay_off = mac_len + 20;
2671 sig_off = find_signature(m_ptr, rec_size, pay_off, flow_id, flow_seq);
2672 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
2673 sig_ts = get_signature_ts(m_ptr, sig_off);
2677 /* Set latency based on rx/tx and signature timestamp */
2679 if (sig_ts < s_time) {
2680 latency = (guint32)(s_time - sig_ts);
2682 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
2683 /* we look for a large difference between l_time and s_time. */
2684 delta_b = sig_ts - s_time;
2685 if (delta_b > 0x10000000) {
2688 latency = (guint32)delta_b;
2693 * Fill up the per-packet header.
2695 * We include the length of the metadata headers in the packet lengths.
2697 * The maximum value of actual_octets is 65535, which, even after
2698 * adding the lengths of the metadata headers, is less than
2699 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
2701 phdr->len = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
2702 phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
2704 phdr->ts.secs = (time_t)s_sec;
2705 phdr->ts.nsecs = (int)(s_usec * 1000);
2706 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
2708 phdr->rec_type = REC_TYPE_PACKET;
2709 phdr->presence_flags = WTAP_HAS_TS;
2711 /*etap_hdr.vw_ip_length = (guint16)ip_len;*/
2713 ws_buffer_assure_space(buf, phdr->caplen);
2714 data_ptr = ws_buffer_start_ptr(buf);
2717 * Generate and copy out the common metadata headers,
2718 * set the port type to 1 (Ethernet).
2720 * All values are copied out in little-endian byte order.
2722 /* 1st octet of record for port_type and command (command is 0, hence RX) */
2723 phtole8(&data_ptr[bytes_written], ETHERNET_PORT);
2725 /* 2nd octet of record for fpga version (Ethernet, hence non-OCTO) */
2726 phtole8(&data_ptr[bytes_written], 0);
2729 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN);
2731 phtoles(&data_ptr[bytes_written], msdu_length);
2733 phtolel(&data_ptr[bytes_written], flow_id);
2735 phtoles(&data_ptr[bytes_written], vc_id);
2737 phtoles(&data_ptr[bytes_written], flow_seq);
2739 if (!IS_TX && (sig_ts != 0)) {
2740 phtolel(&data_ptr[bytes_written], latency);
2742 phtolel(&data_ptr[bytes_written], 0);
2745 phtolel(&data_ptr[bytes_written], sig_ts);
2747 phtolell(&data_ptr[bytes_written], start_time) /* record start & end times of frame */
2749 phtolell(&data_ptr[bytes_written], end_time);
2751 phtolel(&data_ptr[bytes_written], d_time);
2755 * Generate and copy out the Ethernet metadata headers.
2757 * All values are copied out in little-endian byte order.
2759 phtoles(&data_ptr[bytes_written], EXT_ETHERNET_FIELDS_LEN);
2763 vw_flags |= VW_FLAGS_TXF;
2764 if (errors & vwr->FCS_ERROR)
2765 vw_flags |= VW_FLAGS_FCSERR;
2766 phtoles(&data_ptr[bytes_written], vw_flags);
2768 phtoles(&data_ptr[bytes_written], info);
2770 phtolel(&data_ptr[bytes_written], errors);
2772 phtolel(&data_ptr[bytes_written], l4id);
2776 phtolel(&data_ptr[bytes_written], 0);
2780 * Finally, copy the whole MAC frame to the packet buffer as-is.
2781 * This also does not include the last 4 bytes, as those don't
2782 * contain an FCS, they just contain junk.
2784 memcpy(&data_ptr[bytes_written], m_ptr, actual_octets);
2789 /*--------------------------------------------------------------------------------------*/
2790 /* utility to split up and decode a 16-byte message record */
2792 static int decode_msg(vwr_t *vwr, guint8 *rec, int *v_type, int *IS_TX, int *log_mode)
2794 guint8 cmd,fpga_log_mode; /* components of message */
2796 int v_size; /* size of var-len message */
2798 /* break up the message record into its pieces */
2800 fpga_log_mode = rec[1];
2801 fpga_log_mode = ((fpga_log_mode & 0x30) >> 4);
2803 wd2 = pntoh32(&rec[8]);
2804 wd3 = pntoh32(&rec[12]);
2807 *log_mode = fpga_log_mode; /* Log mode = 3, when MPDU data is reduced */
2809 /* now decode based on the command byte */
2815 v_size = (int)(wd2 & 0xffff);
2823 v_size = (int)(wd2 & 0xffff);
2832 v_size = (int)(wd2 & 0xffff);
2837 case COMMAND_RF: /* For RF Modified only */
2841 v_size = (int)(wd2 & 0xffff);
2845 case COMMAND_RFRX: /* For RF_RX Modified only */
2849 v_size = (int)(wd2 & 0xffff);
2859 v_size = (int)(wd2 & 0xffff);
2867 v_size = (int)(wd3 & 0xffff);
2876 *v_type = VT_UNKNOWN;
2884 /*---------------------------------------------------------------------------------------*/
2885 /* Utilities to extract and decode the PHY bit rate from 802.11 PLCP headers (OFDM/CCK). */
2886 /* They are passed a pointer to 4 or 6 consecutive bytes of PLCP header. */
2887 /* The integer returned by the get_xxx_rate() functions is in units of 0.5 Mb/s. */
2888 /* The string returned by the decode_xxx_rate() functions is 3 characters wide. */
2890 static guint8 get_ofdm_rate(const guint8 *plcp)
2892 /* extract the RATE field (LS nibble of first byte) then convert it to the MCS index used by the L1p fields */
2893 switch (plcp[0] & 0x0f) {
2894 case 0x0b: return 4;
2895 case 0x0f: return 5;
2896 case 0x0a: return 6;
2897 case 0x0e: return 7;
2898 case 0x09: return 8;
2899 case 0x0d: return 9;
2900 case 0x08: return 10;
2901 case 0x0c: return 11;
2906 static guint8 get_cck_rate(const guint8 *plcp)
2908 /* extract rate from the SIGNAL field then convert it to the MCS index used by the L1p fields */
2910 case 0x0a: return 0;
2911 case 0x14: return 1;
2912 case 0x37: return 2;
2913 case 0x6e: return 3;
2918 /*--------------------------------------------------------------------------------------*/
2919 /* utility to set up offsets and bitmasks for decoding the stats blocks */
2921 static void setup_defaults(vwr_t *vwr, guint16 fpga)
2926 vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
2928 vwr->VALID_OFF = vVW510021_W_VALID_OFF;
2929 vwr->MTYPE_OFF = vVW510021_W_MTYPE_OFF;
2930 vwr->VCID_OFF = vVW510021_W_VCID_OFF;
2931 vwr->FLOWSEQ_OFF = vVW510021_W_FLOWSEQ_OFF;
2932 vwr->FLOWID_OFF = vVW510021_W_FLOWID_OFF;
2934 /*vwr->OCTET_OFF = v22_W_OCTET_OFF;*/
2936 vwr->ERRORS_OFF = vVW510021_W_ERRORS_OFF;
2937 vwr->PATN_OFF = vVW510021_W_MATCH_OFF;
2938 vwr->RSSI_OFF = vVW510021_W_RSSI_TXPOWER_OFF;
2939 vwr->STARTT_OFF = vVW510021_W_STARTT_OFF;
2940 vwr->ENDT_OFF = vVW510021_W_ENDT_OFF;
2941 vwr->LATVAL_OFF = vVW510021_W_LATVAL_OFF;
2942 vwr->INFO_OFF = vVW510021_W_INFO_OFF;
2943 vwr->FPGA_VERSION_OFF = S2_W_FPGA_VERSION_OFF;
2944 vwr->HEADER_VERSION_OFF = vVW510021_W_HEADER_VERSION_OFF;
2945 vwr->OCTET_OFF = vVW510021_W_MSDU_LENGTH_OFF;
2946 vwr->L1P_1_OFF = vVW510021_W_L1P_1_OFF;
2947 vwr->L1P_2_OFF = vVW510021_W_L1P_2_OFF;
2948 vwr->L4ID_OFF = vVW510021_W_L4ID_OFF;
2949 vwr->IPLEN_OFF = vVW510021_W_IPLEN_OFF;
2950 vwr->PLCP_LENGTH_OFF = vVW510021_W_PLCP_LENGTH_OFF;
2952 vwr->MT_MASK = vVW510021_W_SEL_MASK;
2953 vwr->MCS_INDEX_MASK = vVW510021_W_MCS_MASK;
2954 vwr->VCID_MASK = 0xffff;
2955 vwr->FLOW_VALID = vVW510021_W_FLOW_VALID;
2956 vwr->STATS_START_OFF = vVW510021_W_HEADER_LEN;
2957 vwr->FCS_ERROR = vVW510021_W_FCS_ERROR;
2958 vwr->CRYPTO_ERR = v22_W_CRYPTO_ERR;
2959 vwr->RETRY_ERR = v22_W_RETRY_ERR;
2961 /*vwr->STATS_START_OFF = 0;*/
2963 vwr->RXTX_OFF = vVW510021_W_RXTX_OFF;
2965 vwr->MT_10_HALF = 0;
2966 vwr->MT_10_FULL = 0;
2967 vwr->MT_100_HALF = 0;
2968 vwr->MT_100_FULL = 0;
2969 vwr->MT_1G_HALF = 0;
2970 vwr->MT_1G_FULL = 0;
2971 vwr->MT_CCKL = v22_W_MT_CCKL;
2972 vwr->MT_CCKS = v22_W_MT_CCKS;
2973 /*vwr->MT_OFDM = vVW510021_W_MT_OFDM;*/
2975 vwr->WEPTYPE = vVW510021_W_WEPTYPE;
2976 vwr->TKIPTYPE = vVW510021_W_TKIPTYPE;
2977 vwr->CCMPTYPE = vVW510021_W_CCMPTYPE;
2979 vwr->FRAME_TYPE_OFF = vVW510021_W_FRAME_TYPE_OFF;
2980 vwr->IS_TCP = vVW510021_W_IS_TCP;
2981 vwr->IS_UDP = vVW510021_W_IS_UDP;
2982 vwr->IS_ICMP = vVW510021_W_IS_ICMP;
2983 vwr->IS_IGMP = vVW510021_W_IS_IGMP;
2984 vwr->IS_QOS = vVW510021_W_QOS_VALID;
2987 * vVW510021_W_STATS_HEADER_LEN = 8 is:
2989 * 2 bytes of l1p_1/l1p_2;
2991 * 2 bytes of MSDU length + other bits
2995 * The 12 is for 11 bytes of PLCP and 1 byte of pad
2998 vwr->MPDU_OFF = vVW510021_W_STATS_HEADER_LEN + 12;
3003 vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
3004 vwr->PLCP_LENGTH_OFF = 16;
3009 * 2 bytes of l1p_1/l1p_2;
3010 * 1 byte of signal bandwidth mask;
3011 * 1 byte of antenna port energy;
3012 * 4 bytes of per-antenna RSSI;
3013 * 1 byte of L1InfoC;
3014 * 3 bytes of MSDU length;
3015 * 4 bytes of something;
3018 vwr->MPDU_OFF = 16 + 16;
3022 case vVW510012_E_FPGA:
3023 vwr->STATS_LEN = v22_E_STATS_LEN;
3025 vwr->VALID_OFF = v22_E_VALID_OFF;
3026 vwr->MTYPE_OFF = v22_E_MTYPE_OFF;
3027 vwr->VCID_OFF = v22_E_VCID_OFF;
3028 vwr->FLOWSEQ_OFF = v22_E_FLOWSEQ_OFF;
3029 vwr->FLOWID_OFF = v22_E_FLOWID_OFF;
3030 vwr->OCTET_OFF = v22_E_OCTET_OFF;
3031 vwr->ERRORS_OFF = v22_E_ERRORS_OFF;
3032 vwr->PATN_OFF = v22_E_PATN_OFF;
3033 vwr->RSSI_OFF = v22_E_RSSI_OFF;
3034 vwr->STARTT_OFF = v22_E_STARTT_OFF;
3035 vwr->ENDT_OFF = v22_E_ENDT_OFF;
3036 vwr->LATVAL_OFF = v22_E_LATVAL_OFF;
3037 vwr->INFO_OFF = v22_E_INFO_OFF;
3038 vwr->L4ID_OFF = v22_E_L4ID_OFF;
3040 vwr->IS_RX = v22_E_IS_RX;
3041 vwr->MT_MASK = v22_E_MT_MASK;
3042 vwr->VCID_MASK = v22_E_VCID_MASK;
3043 vwr->FLOW_VALID = v22_E_FLOW_VALID;
3044 vwr->FCS_ERROR = v22_E_FCS_ERROR;
3046 vwr->RX_DECRYPTS = v22_E_RX_DECRYPTS;
3047 vwr->TX_DECRYPTS = v22_E_TX_DECRYPTS;
3048 vwr->FC_PROT_BIT = v22_E_FC_PROT_BIT;
3050 vwr->MT_10_HALF = v22_E_MT_10_HALF;
3051 vwr->MT_10_FULL = v22_E_MT_10_FULL;
3052 vwr->MT_100_HALF = v22_E_MT_100_HALF;
3053 vwr->MT_100_FULL = v22_E_MT_100_FULL;
3054 vwr->MT_1G_HALF = v22_E_MT_1G_HALF;
3055 vwr->MT_1G_FULL = v22_E_MT_1G_FULL;
3060 vwr->FRAME_TYPE_OFF = v22_E_FRAME_TYPE_OFF;
3061 vwr->IS_TCP = v22_E_IS_TCP;
3062 vwr->IS_UDP = v22_E_IS_UDP;
3063 vwr->IS_ICMP = v22_E_IS_ICMP;
3064 vwr->IS_IGMP = v22_E_IS_IGMP;
3065 vwr->IS_QOS = v22_E_IS_QOS;
3066 vwr->IS_VLAN = v22_E_IS_VLAN;
3072 vwr->STATS_LEN = v22_W_STATS_LEN;
3074 vwr->MTYPE_OFF = v22_W_MTYPE_OFF;
3075 vwr->VALID_OFF = v22_W_VALID_OFF;
3076 vwr->VCID_OFF = v22_W_VCID_OFF;
3077 vwr->FLOWSEQ_OFF = v22_W_FLOWSEQ_OFF;
3078 vwr->FLOWID_OFF = v22_W_FLOWID_OFF;
3079 vwr->OCTET_OFF = v22_W_OCTET_OFF;
3080 vwr->ERRORS_OFF = v22_W_ERRORS_OFF;
3081 vwr->PATN_OFF = v22_W_PATN_OFF;
3082 vwr->RSSI_OFF = v22_W_RSSI_OFF;
3083 vwr->STARTT_OFF = v22_W_STARTT_OFF;
3084 vwr->ENDT_OFF = v22_W_ENDT_OFF;
3085 vwr->LATVAL_OFF = v22_W_LATVAL_OFF;
3086 vwr->INFO_OFF = v22_W_INFO_OFF;
3087 vwr->L4ID_OFF = v22_W_L4ID_OFF;
3088 vwr->IPLEN_OFF = v22_W_IPLEN_OFF;
3089 vwr->PLCP_LENGTH_OFF = v22_W_PLCP_LENGTH_OFF;
3091 vwr->FCS_ERROR = v22_W_FCS_ERROR;
3092 vwr->CRYPTO_ERR = v22_W_CRYPTO_ERR;
3093 vwr->PAYCHK_ERR = v22_W_PAYCHK_ERR;
3094 vwr->RETRY_ERR = v22_W_RETRY_ERR;
3095 vwr->IS_RX = v22_W_IS_RX;
3096 vwr->MT_MASK = v22_W_MT_MASK;
3097 vwr->VCID_MASK = v22_W_VCID_MASK;
3098 vwr->FLOW_VALID = v22_W_FLOW_VALID;
3100 vwr->RX_DECRYPTS = v22_W_RX_DECRYPTS;
3101 vwr->TX_DECRYPTS = v22_W_TX_DECRYPTS;
3102 vwr->FC_PROT_BIT = v22_W_FC_PROT_BIT;
3104 vwr->MT_10_HALF = 0;
3105 vwr->MT_10_FULL = 0;
3106 vwr->MT_100_HALF = 0;
3107 vwr->MT_100_FULL = 0;
3108 vwr->MT_1G_HALF = 0;
3109 vwr->MT_1G_FULL = 0;
3110 vwr->MT_CCKL = v22_W_MT_CCKL;
3111 vwr->MT_CCKS = v22_W_MT_CCKS;
3112 vwr->MT_OFDM = v22_W_MT_OFDM;
3114 vwr->WEPTYPE = v22_W_WEPTYPE;
3115 vwr->TKIPTYPE = v22_W_TKIPTYPE;
3116 vwr->CCMPTYPE = v22_W_CCMPTYPE;
3118 vwr->FRAME_TYPE_OFF = v22_W_FRAME_TYPE_OFF;
3119 vwr->IS_TCP = v22_W_IS_TCP;
3120 vwr->IS_UDP = v22_W_IS_UDP;
3121 vwr->IS_ICMP = v22_W_IS_ICMP;
3122 vwr->IS_IGMP = v22_W_IS_IGMP;
3123 vwr->IS_QOS = v22_W_IS_QOS;
3127 /* Ethernet frames */
3128 case vVW510024_E_FPGA:
3129 vwr->STATS_LEN = vVW510024_E_STATS_LEN;
3131 vwr->VALID_OFF = vVW510024_E_VALID_OFF;
3132 vwr->VCID_OFF = vVW510024_E_VCID_OFF;
3133 vwr->FLOWSEQ_OFF = vVW510024_E_FLOWSEQ_OFF;
3134 vwr->FLOWID_OFF = vVW510024_E_FLOWID_OFF;
3135 vwr->OCTET_OFF = vVW510024_E_MSDU_LENGTH_OFF;
3136 vwr->ERRORS_OFF = vVW510024_E_ERRORS_OFF;
3137 vwr->PATN_OFF = vVW510024_E_MATCH_OFF;
3138 vwr->STARTT_OFF = vVW510024_E_STARTT_OFF;
3139 vwr->ENDT_OFF = vVW510024_E_ENDT_OFF;
3140 vwr->LATVAL_OFF = vVW510024_E_LATVAL_OFF;
3141 vwr->INFO_OFF = vVW510024_E_INFO_OFF;
3142 vwr->L4ID_OFF = vVW510024_E_L4ID_OFF;
3143 vwr->IPLEN_OFF = vVW510024_E_IPLEN_OFF;
3145 vwr->FPGA_VERSION_OFF = vVW510024_E_FPGA_VERSION_OFF;
3146 vwr->HEADER_VERSION_OFF = vVW510024_E_HEADER_VERSION_OFF;
3148 vwr->VCID_MASK = vVW510024_E_VCID_MASK;
3149 vwr->FLOW_VALID = vVW510024_E_FLOW_VALID;
3150 vwr->FCS_ERROR = v22_E_FCS_ERROR;
3152 vwr->FRAME_TYPE_OFF = vVW510024_E_FRAME_TYPE_OFF;
3153 vwr->IS_TCP = vVW510024_E_IS_TCP;
3154 vwr->IS_UDP = vVW510024_E_IS_UDP;
3155 vwr->IS_ICMP = vVW510024_E_IS_ICMP;
3156 vwr->IS_IGMP = vVW510024_E_IS_IGMP;
3157 vwr->IS_QOS = vVW510024_E_QOS_VALID;
3158 vwr->IS_VLAN = vVW510024_E_IS_VLAN;
3163 #define SIG_SCAN_RANGE 64 /* range of signature scanning region */
3165 /* Utility routine: check that signature is at specified location; scan for it if not. */
3166 /* If we can't find a signature at all, then simply return the originally supplied offset. */
3167 int find_signature(const guint8 *m_ptr, int rec_size, int pay_off, guint32 flow_id, guint8 flow_seq)
3169 int tgt; /* temps */
3172 /* initial check is very simple: look for a '0xdd' at the target location */
3173 if (m_ptr[pay_off] == 0xdd) /* if magic byte is present */
3174 return pay_off; /* got right offset, return it */
3176 /* Hmmm, signature magic byte is not where it is supposed to be; scan from start of */
3177 /* payload until maximum scan range exhausted to see if we can find it. */
3178 /* The scanning process consists of looking for a '0xdd', then checking for the correct */
3179 /* flow ID and sequence number at the appropriate offsets. */
3180 for (tgt = pay_off; tgt < (rec_size); tgt++) {
3181 if (m_ptr[tgt] == 0xdd) { /* found magic byte? check fields */
3182 if ((tgt + 15 < rec_size) && (m_ptr[tgt + 15] == 0xe2)) {
3183 if (m_ptr[tgt + 4] != flow_seq)
3186 fid = pletoh24(&m_ptr[tgt + 1]);
3193 else if (tgt + SIG_FSQ_OFF < rec_size)
3194 { /* out which one... */
3195 if (m_ptr[tgt + SIG_FSQ_OFF] != flow_seq) /* check sequence number */
3196 continue; /* if failed, keep scanning */
3198 fid = pletoh24(&m_ptr[tgt + SIG_FID_OFF]); /* assemble flow ID from signature */
3199 if (fid != flow_id) /* check flow ID against expected */
3200 continue; /* if failed, keep scanning */
3202 /* matched magic byte, sequence number, flow ID; found the signature */
3203 return (tgt); /* return offset of signature */
3208 /* failed to find the signature, return the original offset as default */
3212 /* utility routine: harvest the signature time stamp from the data frame */
3213 guint64 get_signature_ts(const guint8 *m_ptr,int sig_off)
3218 if (m_ptr[sig_off + 15] == 0xe2)
3223 sig_ts = pletoh32(&m_ptr[sig_off + ts_offset]);
3225 return (sig_ts & 0xffffffff);
3229 get_legacy_rate(guint8 rate_index)
3231 /* Rate conversion data */
3232 static const float canonical_rate_legacy[] = {1.0f, 2.0f, 5.5f, 11.0f, 6.0f, 9.0f, 12.0f, 18.0f, 24.0f, 36.0f, 48.0f, 54.0f};
3234 float bitrate = 0.0f;
3236 if (rate_index < G_N_ELEMENTS(canonical_rate_legacy))
3237 bitrate = canonical_rate_legacy[rate_index];
3243 get_ht_rate(guint8 mcs_index, guint16 rflags)
3245 /* Rate conversion data */
3246 static const int canonical_ndbps_20_ht[8] = {26, 52, 78, 104, 156, 208, 234, 260};
3247 static const int canonical_ndbps_40_ht[8] = {54, 108, 162, 216, 324, 432, 486, 540};
3249 float symbol_tx_time, bitrate;
3252 if (rflags & FLAGS_CHAN_SHORTGI)
3253 symbol_tx_time = 3.6f;
3255 symbol_tx_time = 4.0f;
3257 if (rflags & FLAGS_CHAN_40MHZ)
3258 ndbps = canonical_ndbps_40_ht[mcs_index - 8*(int)(mcs_index/8)];
3260 ndbps = canonical_ndbps_20_ht[mcs_index - 8*(int)(mcs_index/8)];
3262 bitrate = (ndbps * (((int)(mcs_index >> 3) + 1))) / symbol_tx_time;
3268 get_vht_rate(guint8 mcs_index, guint16 rflags, guint8 nss)
3270 /* Rate conversion data */
3271 static const int canonical_ndbps_20_vht[9] = {26, 52, 78, 104, 156, 208, 234, 260, 312};
3272 static const int canonical_ndbps_40_vht[10] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
3273 static const int canonical_ndbps_80_vht[10] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
3275 float symbol_tx_time, bitrate;
3277 if (rflags & FLAGS_CHAN_SHORTGI)
3278 symbol_tx_time = 3.6f;
3280 symbol_tx_time = 4.0f;
3283 * Check for the out of range mcs_index.
3284 * Should never happen, but if mcs index is greater than 9 just
3289 if (rflags & FLAGS_CHAN_40MHZ)
3290 bitrate = (canonical_ndbps_40_vht[mcs_index] * nss) / symbol_tx_time;
3291 else if (rflags & FLAGS_CHAN_80MHZ)
3292 bitrate = (canonical_ndbps_80_vht[mcs_index] * nss) / symbol_tx_time;
3297 /* This is a special case for 20 MHz. */
3299 bitrate = 1040 / symbol_tx_time;
3301 bitrate = 2080 / symbol_tx_time;
3306 bitrate = (canonical_ndbps_20_vht[mcs_index] * nss) / symbol_tx_time;
3313 vwr_process_rec_data(FILE_T fh, int rec_size,
3314 struct wtap_pkthdr *phdr, Buffer *buf, vwr_t *vwr,
3315 int IS_TX, int log_mode, int *err, gchar **err_info)
3317 guint8* rec; /* local buffer (holds input record) */
3318 gboolean ret = FALSE;
3320 rec = (guint8*)g_malloc(B_SIZE);
3322 /* Read over the entire record (frame + trailer) into a local buffer. */
3323 /* If we don't get it all, then declare an error, we can't process the frame. */
3324 if (!wtap_read_bytes(fh, rec, rec_size, err, err_info))
3330 /* now format up the frame data */
3331 switch (vwr->FPGA_VERSION)
3334 ret = vwr_read_s1_W_rec(vwr, phdr, buf, rec, rec_size, err, err_info);
3337 ret = vwr_read_s2_W_rec(vwr, phdr, buf, rec, rec_size, IS_TX, err, err_info);
3340 ret = vwr_read_s3_W_rec(vwr, phdr, buf, rec, rec_size, IS_TX, log_mode, err, err_info);
3342 case vVW510012_E_FPGA:
3343 case vVW510024_E_FPGA:
3344 ret = vwr_read_rec_data_ethernet(vwr, phdr, buf, rec, rec_size, IS_TX, err, err_info);
3348 g_assert_not_reached();
3357 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3362 * indent-tabs-mode: nil
3365 * vi: set shiftwidth=4 tabstop=8 expandtab:
3366 * :indentSize=4:tabSize=8:noTabs=true: