2 * Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
5 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "file_wrappers.h"
18 #include <wsutil/ws_assert.h>
20 /* platform-specific definitions for portability */
22 /* unsigned long long constants */
23 # define NS_IN_US UINT64_C(1000) /* nanoseconds-to-microseconds */
24 # define NS_IN_SEC UINT64_C(1000000000) /* nanoseconds-to-seconds */
25 # define US_IN_SEC UINT64_C(1000000) /* microseconds-to-seconds */
26 # define LL_ZERO UINT64_C(0) /* zero in unsigned long long */
29 * Fetch a 64-bit value in "Corey-endian" form.
31 #define pcoreytohll(p) ((uint64_t)*((const uint8_t *)(p)+4)<<56| \
32 (uint64_t)*((const uint8_t *)(p)+5)<<48| \
33 (uint64_t)*((const uint8_t *)(p)+6)<<40| \
34 (uint64_t)*((const uint8_t *)(p)+7)<<32| \
35 (uint64_t)*((const uint8_t *)(p)+0)<<24| \
36 (uint64_t)*((const uint8_t *)(p)+1)<<16| \
37 (uint64_t)*((const uint8_t *)(p)+2)<<8| \
38 (uint64_t)*((const uint8_t *)(p)+3)<<0)
41 * Fetch a 48-bit value in "Corey-endian" form; it's stored as
42 * a 64-bit Corey-endian value, with the upper 16 bits ignored.
44 #define pcorey48tohll(p) ((uint64_t)*((const uint8_t *)(p)+6)<<40| \
45 (uint64_t)*((const uint8_t *)(p)+7)<<32| \
46 (uint64_t)*((const uint8_t *)(p)+0)<<24| \
47 (uint64_t)*((const uint8_t *)(p)+1)<<16| \
48 (uint64_t)*((const uint8_t *)(p)+2)<<8| \
49 (uint64_t)*((const uint8_t *)(p)+3)<<0)
51 /* .vwr log file defines */
52 #define B_SIZE 32768 /* max var len message = 32 kB */
53 #define VT_FRAME 0 /* varlen msg is a frame */
54 #define VT_CPMSG 1 /* varlen msg is a CP<->PP msg */
55 #define VT_UNKNOWN -1 /* varlen msg is unknown */
56 #define MAX_TRACKED_CLIENTS 1024 /* track 1024 clients */
57 #define MAX_TRACKED_FLOWS 65536 /* and 64K flows */
60 * The file consists of a sequence of records.
61 * A record begins with a 16-byte header, the first 8 bytes of which
62 * begin with a byte containing a command plus transmit-receive flags.
64 * Following that are two big-endian 32-bit quantities; for some records
65 * one or the other of them is the length of the rest of the record.
66 * Other records contain only the header.
68 #define VW_RECORD_HEADER_LENGTH 16
71 * Maximum number of bytes to read looking for a valid frame starting
72 * with a command byte to determine if this is our file type. Arbitrary.
74 #define VW_BYTES_TO_CHECK 0x3FFFFFFFU
76 /* Command byte values */
77 #define COMMAND_RX 0x21
78 #define COMMAND_TX 0x31
79 #define COMMAND_RFN 0x30
80 #define COMMAND_RF 0x38
81 #define COMMAND_RFRX 0x39
84 * The data in packet records begins with a sequence of metadata headers.
86 * For packet records from FPGA versions < 48:
88 * The first header is the IxVeriWave common header, and that's
89 * followed either by a WLAN metadata header or an Ethernet
90 * metadata header. The port type field indicates whether it's
91 * a WLAN packet or an Ethernet packet. Following that may, for
92 * WLAN, be 1 octet of information from the FPGA and 16 bytes of
93 * data including the PLCP header. After that comes the WLAN or
94 * Ethernet frame, beginning with the MAC header.
96 * For packet records from FPGA versions >= 48:
98 * The first header contains only a 1-octet port type value, which
99 * has a packet type value in the upper 4 bits and zero in the lower
100 * 4 bits. NOTE: this is indistinguishable from an old FPGA header
101 * if the packet type value is 0.
103 * If the packet type value isn't 3, the port type value is followed
104 * by a 1-octet FPGA version number, which is followed by a timestamp
107 * If the packet type value is 3 or 4, the next item is an RF metadata
108 * header. For type 3, that immediately follows the port number octet,
109 * otherwise it immediately follows the timestamp header.
111 * If the packet type isn't 3, the next item is a WLAN metadata header,
112 * in a format different from the WLAN metadata header for FPGA versions
113 * < 48. That is followed by a PLCP header, which is followed by a
114 * header giving additional layer 2 through 4 metadata.
116 * Following those headers is the WLAN or Ethernet frame, beginning with
121 * IxVeriWave common header:
123 * 1 octet - port type
124 * 1 octet - FPGA version, or 0
125 * 2 octets - length of the common header
126 * 2 octets - MSDU length
129 * 2 octets - flow sequence number
130 * 4 octets - latency or 0
131 * 4 octets - lower 32 bits of signature time stamp
132 * 8 octets - start time
133 * 8 octets - end time
134 * 4 octets - delta(?) time
137 /* Size of the IxVeriWave common header */
138 #define STATS_COMMON_FIELDS_LEN (1+1+2+2+4+2+2+4+4+8+8+4)
142 #define ETHERNET_PORT 1
144 /* For VeriWave WLAN and Ethernet metadata headers vw_flags field */
145 #define VW_FLAGS_TXF 0x01 /* frame was transmitted */
146 #define VW_FLAGS_FCSERR 0x02 /* FCS error detected */
149 * VeriWave WLAN metadata header:
151 * 2 octets - header length
153 * 2 octets - channel flags
154 * 2 octets - PHY rate
155 * 1 octet - PLCP type
156 * 1 octet - MCS index
157 * 1 octet - number of spatial streams
159 * 1 octet - antenna b signal power, or 100 if missing
160 * 1 octet - antenna c signal power, or 100 if missing
161 * 1 octet - antenna d signal power, or 100 if missing
163 * 2 octets - VeriWave flags
169 /* Size of the VeriWave WLAN metadata header */
170 #define EXT_WLAN_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
172 /* Flags, for rflags field */
173 #define FLAGS_SHORTPRE 0x0002 /* sent/received with short preamble */
174 #define FLAGS_WEP 0x0004 /* sent/received with WEP encryption */
175 #define FLAGS_CHAN_HT 0x0040 /* In HT mode */
176 #define FLAGS_CHAN_VHT 0x0080 /* VHT Mode */
177 #define FLAGS_CHAN_SHORTGI 0x0100 /* Short guard interval */
178 #define FLAGS_CHAN_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
179 #define FLAGS_CHAN_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
180 #define FLAGS_CHAN_160MHZ 0x0800 /* 160 Mhz channel bandwidth */
182 /* Channel flags, for channel flags field */
183 #define CHAN_CCK 0x0020 /* CCK channel */
184 #define CHAN_OFDM 0x0040 /* OFDM channel */
186 /* For VeriWave WLAN metadata header vw_flags field */
187 #define VW_FLAGS_RETRERR 0x04 /* excess retry error detected */
188 #define VW_FLAGS_DCRERR 0x10 /* decrypt error detected (WLAN) */
189 #define VW_FLAGS_ENCMSK 0x60 /* encryption type mask */
190 /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
191 #define VW_FLAGS_IS_WEP 0x20 /* WEP */
192 #define VW_FLAGS_IS_TKIP 0x40 /* TKIP */
193 #define VW_FLAGS_IS_CCMP 0x60 /* CCMP */
196 * VeriWave Ethernet metadata header:
198 * 2 octets - header length
199 * 2 octets - VeriWave flags
202 * 4 octets - layer 4 ID
205 * Ethernet frame follows, beginning with the MAC header
208 /* Size of the VeriWave Ethernet metadata header */
209 #define EXT_ETHERNET_FIELDS_LEN (2+2+2+4+4+4)
212 * OCTO timestamp header.
214 * 4 octets - latency or 0
215 * 4 octets - lower 32 bits of signature time stamp
216 * 8 octets - start time
217 * 8 octets - end time
218 * 4 octets - delta(?) time
221 /* Size of Timestamp header */
222 #define OCTO_TIMESTAMP_FIELDS_LEN (4+4+8+8+4+4)
225 * OCTO layer 1-4 header:
227 * 2 octets - header length
229 * 1 octet - number of spatial streams
230 * 2 octets - PHY rate
233 * 1 octet - antenna b signal power, or 100 if missing
234 * 1 octet - antenna c signal power, or 100 if missing
235 * 1 octet - antenna d signal power, or 100 if missing
236 * 1 octet - signal bandwidth mask
237 * 1 octet - antenna port energy detect and VU_MASK
238 * 1 octet - L1InfoC or 0
239 * 2 octets - MSDU length
241 * 4 octets - BM, BV, CV, BSSID and ClientID
242 * 2 octets - FV, QT, HT, L4V, TID and WLAN type
243 * 1 octets - flow sequence number
245 * 2 octets - layer 4 ID
246 * 4 octets - payload decode
251 /* Size of Layer-1, PLCP, and Layer-2/4 header in case of OCTO version FPGA */
252 #define OCTO_LAYER1TO4_LEN (2+14+16+23)
255 * OCTO modified RF layer:
258 * 3 octets - unused (zero)
259 * 8 octets - noise for 4 ports
260 * 8 octets - signal/noise ration for 4 ports
261 * 8 octets - PFE for 4 ports
262 * 8 octets - EVM SIG data for 4 ports
263 * 8 octets - EVM SIG pilot for 4 ports
264 * 8 octets - EVM Data data for 4 ports
265 * 8 octets - EVM Data pilot for 4 ports
266 * 8 octets - EVM worst symbol for 4 ports
267 * 8 octets - CONTEXT_P for 4 ports
270 * 24 octets of additional data
273 /* Size of RF header, if all fields were supplied */
274 #define OCTO_RF_MOD_ACTUAL_LEN 100 /* */
276 /* Size of RF header with the fields we do supply */
277 #define OCTO_MODIFIED_RF_LEN 76 /* 24 bytes of RF are not displayed*/
279 /*Offset of different parameters of RF header for port-1*/
280 #define RF_PORT_1_NOISE_OFF 4
281 #define RF_PORT_1_SNR_OFF 6
282 #define RF_PORT_1_PFE_OFF 8
283 #define RF_PORT_1_CONTEXT_OFF 10
284 #define RF_PORT_1_EVM_SD_SIG_OFF 12
285 #define RF_PORT_1_EVM_SP_SIG_OFF 14
286 #define RF_PORT_1_EVM_SD_DATA_OFF 16
287 #define RF_PORT_1_EVM_SP_DATA_OFF 18
288 #define RF_PORT_1_DSYMBOL_IDX_OFF 22
289 #define RF_INTER_PORT_GAP_OFF 24 /*As size of RF information per port is 24 bytes*/
290 #define RF_NUMBER_OF_PORTS 4
292 /* FPGA-generated frame buffer STATS block offsets and definitions */
294 /* definitions for v2.2 frames, Ethernet format */
295 #define v22_E_STATS_LEN 44 /* length of stats block trailer */
296 #define v22_E_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
297 #define v22_E_MTYPE_OFF 1 /* offset of modulation type */
298 #define v22_E_VCID_OFF 2 /* offset of VC ID */
299 #define v22_E_FLOWSEQ_OFF 4 /* offset of signature sequence number */
300 #define v22_E_FLOWID_OFF 5 /* offset of flow ID */
301 #define v22_E_OCTET_OFF 8 /* offset of octets */
302 #define v22_E_ERRORS_OFF 10 /* offset of error vector */
303 #define v22_E_PATN_OFF 12 /* offset of pattern match vector */
304 #define v22_E_L4ID_OFF 12
305 #define v22_E_IPLEN_OFF 14
306 #define v22_E_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
307 #define v22_E_RSSI_OFF 21 /* RSSI (NOTE: invalid for Ethernet) */
308 #define v22_E_STARTT_OFF 20 /* offset of start time, 64 bits */
309 #define v22_E_ENDT_OFF 28 /* offset of end time, 64 bits */
310 #define v22_E_LATVAL_OFF 36 /* offset of latency, 32 bits */
311 #define v22_E_INFO_OFF 40 /* NO INFO FIELD IN ETHERNET STATS! */
312 #define v22_E_DIFFERENTIATOR_OFF 0 /* offset to determine whether */
313 /* eth/802.11, 8 bits */
315 #define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
316 #define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
317 #define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
318 #define v22_E_MT_100_FULL 3 /* 100 Mb/s full-duplex */
319 #define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
320 #define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
323 #define v22_E_FCS_ERROR 0x0002 /* FCS error flag in error vector */
324 #define v22_E_CRYPTO_ERR 0x1f00 /* RX decrypt error flags (UNUSED) */
325 #define v22_E_SIG_ERR 0x0004 /* signature magic byte mismatch */
326 #define v22_E_PAYCHK_ERR 0x0008 /* payload checksum failure */
327 #define v22_E_RETRY_ERR 0x0400 /* excessive retries on TX fail (UNUSED)*/
329 /* Masks and defines */
330 #define v22_E_IS_RX 0x08 /* TX/RX bit in STATS block */
331 #define v22_E_MT_MASK 0x07 /* modulation type mask (UNUSED) */
333 #define v22_E_VCID_MASK 0x03ff /* VC ID is only 10 bits */
335 #define v22_E_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
337 #define v22_E_DIFFERENTIATOR_MASK 0x3F /* mask to differentiate ethernet from */
339 /* Bits in FRAME_TYPE field */
340 #define v22_E_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
341 #define v22_E_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
342 #define v22_E_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
343 #define v22_E_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
345 /* Bits in MTYPE field (WLAN only) */
346 #define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
348 #define v22_E_IS_VLAN 0x00200000
350 #define v22_E_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted (UNUSED) */
351 #define v22_E_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted (UNUSED) */
353 #define v22_E_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
355 #define v22_E_IS_ETHERNET 0x00700000 /* bits set in frame type if ethernet */
356 #define v22_E_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
358 /* definitions for v2.2 frames, WLAN format for VW510006 FPGA*/
359 #define v22_W_STATS_LEN 64 /* length of stats block trailer */
360 #define v22_W_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
361 #define v22_W_MTYPE_OFF 1 /* offset of modulation type */
362 #define v22_W_VCID_OFF 2 /* offset of VC ID */
363 #define v22_W_FLOWSEQ_OFF 4 /* offset of signature sequence number */
364 #define v22_W_FLOWID_OFF 5 /* offset of flow ID */
365 #define v22_W_OCTET_OFF 8 /* offset of octets */
366 #define v22_W_ERRORS_OFF 10 /* offset of error vector */
367 #define v22_W_PATN_OFF 12
368 #define v22_W_L4ID_OFF 12
369 #define v22_W_IPLEN_OFF 14
370 #define v22_W_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
371 #define v22_W_RSSI_OFF 21 /* RSSI (NOTE: RSSI must be negated!) */
372 #define v22_W_STARTT_OFF 24 /* offset of start time, 64 bits */
373 #define v22_W_ENDT_OFF 32 /* offset of end time, 64 bits */
374 #define v22_W_LATVAL_OFF 40 /* offset of latency, 32 bits */
375 #define v22_W_INFO_OFF 54 /* offset of INFO field, 16 LSBs */
376 #define v22_W_DIFFERENTIATOR_OFF 20 /* offset to determine whether */
377 /* eth/802.11, 32 bits */
379 #define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
381 /* Modulation types */
382 #define v22_W_MT_CCKL 0 /* CCK modulation, long preamble */
383 #define v22_W_MT_CCKS 1 /* CCK modulation, short preamble */
384 #define v22_W_MT_OFDM 2 /* OFDM modulation */
386 /* Bits in FRAME_TYPE field */
387 #define v22_W_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
388 #define v22_W_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
389 #define v22_W_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
390 #define v22_W_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
392 /* Bits in MTYPE field (WLAN only) */
393 #define v22_W_IS_QOS 0x80 /* QoS */
396 #define v22_W_FCS_ERROR 0x0002 /* FCS error flag in error vector */
397 #define v22_W_CRYPTO_ERR 0x1f00 /* RX decrypt error flags */
398 #define v22_W_SIG_ERR 0x0004 /* signature magic byte mismatch */
399 #define v22_W_PAYCHK_ERR 0x0008 /* payload checksum failure */
400 #define v22_W_RETRY_ERR 0x0400 /* excessive retries on TX failure */
402 /* Masks and defines */
403 #define v22_W_IS_RX 0x08 /* TX/RX bit in STATS block */
404 #define v22_W_MT_MASK 0x07 /* modulation type mask */
406 #define v22_W_VCID_MASK 0x01ff /* VC ID is only 9 bits */
408 #define v22_W_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
410 #define v22_W_DIFFERENTIATOR_MASK 0xf0ff /* mask to differentiate ethernet from */
413 #define v22_W_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted bits */
414 #define v22_W_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted bits */
417 #define v22_W_WEPTYPE 0x0001 /* WEP frame */
418 #define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
419 #define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
420 #define v22_W_MPDU_OF_A_MPDU 0x0400 /* MPDU of A-MPDU */
421 #define v22_W_FIRST_MPDU_OF_A_MPDU 0x0800 /* first MPDU of A-MPDU */
422 #define v22_W_LAST_MPDU_OF_A_MPDU 0x1000 /* last MPDU of A-MPDU */
423 #define v22_W_MSDU_OF_A_MSDU 0x2000 /* MSDU of A-MSDU */
424 #define v22_W_FIRST_MSDU_OF_A_MSDU 0x4000 /* first MSDU of A-MSDU */
425 #define v22_W_LAST_MSDU_OF_A_MSDU 0x8000 /* last MSDU of A-MSDU */
427 /* All aggregation flags */
428 #define v22_W_AGGREGATE_FLAGS \
429 (v22_W_MPDU_OF_A_MPDU | \
430 v22_W_FIRST_MPDU_OF_A_MPDU | \
431 v22_W_LAST_MPDU_OF_A_MPDU | \
432 v22_W_MSDU_OF_A_MSDU | \
433 v22_W_FIRST_MSDU_OF_A_MSDU | \
434 v22_W_LAST_MSDU_OF_A_MSDU)
436 #define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
438 #define v22_W_IS_ETHERNET 0x00100000 /* bits set in frame type if ethernet */
439 #define v22_W_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
441 /* definitions for VW510021 FPGA, WLAN format */
444 8 bytes of stat block
445 plcp stuff (11 bytes plcp + 1 byte pad)
447 remaining 48 bytes of stat block
449 /* offsets in the stats block */
450 #define vVW510021_W_STATS_HEADER_LEN 8 /* length of stats block header at beginning of record data */
451 #define vVW510021_W_STATS_TRAILER_LEN 48 /* length of stats block trailer after the plcp portion*/
452 #define vVW510021_W_STARTT_OFF 0 /* offset of start time, 64 bits */
453 #define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
454 #define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
455 #define vVW510021_W_VALID_OFF 20 /* 2 Bytes with different validity bits */
456 #define vVW510021_W_INFO_OFF 22 /* offset of INFO field, 16 LSBs */
457 #define vVW510021_W_FRAME_TYPE_OFF 24
458 #define vVW510021_W_L4ID_OFF 28
459 #define vVW510021_W_IPLEN_OFF 30 /* offset of IP Total Length field */
460 #define vVW510021_W_FLOWSEQ_OFF 32 /* offset of signature sequence number */
461 #define vVW510021_W_FLOWID_OFF 33 /* offset of flow ID */
462 #define vVW510021_W_LATVAL_OFF 36 /* offset of delay/flowtimestamp, 32b */
463 #define vVW510021_W_DEBUG_OFF 40 /* offset of debug, 16 bits */
464 #define S2_W_FPGA_VERSION_OFF 44 /* offset of fpga version, 16 bits */
465 #define vVW510021_W_MATCH_OFF 47 /* offset of pattern match vector */
467 /* offsets in the header block */
468 #define vVW510021_W_HEADER_LEN 16 /* length of FRAME header */
469 #define vVW510021_W_RXTX_OFF 0 /* rxtx offset, cmd byte of header */
470 #define vVW510021_W_HEADER_VERSION_OFF 9 /* version, 2bytes */
471 #define vVW510021_MSG_LENGTH_OFF 10 /* MSG LENGTH, 2bytes */
472 #define vVW510021_W_DEVICE_TYPE_OFF 8 /* version, 2bytes */
474 /* offsets that occur right after the header */
475 #define vVW510021_W_AFTERHEADER_LEN 8 /* length of STATs info directly after header */
476 #define vVW510021_W_L1P_1_OFF 0 /* offset of 1st byte of layer one info */
477 #define vVW510021_W_L1P_2_OFF 1 /* offset of 2nd byte of layer one info */
478 #define vVW510021_W_MTYPE_OFF vVW510021_W_L1P_2_OFF
479 #define vVW510021_W_PREAMBLE_OFF vVW510021_W_L1P_1_OFF
480 #define vVW510021_W_RSSI_TXPOWER_OFF 2 /* RSSI (NOTE: RSSI must be negated!) */
481 #define vVW510021_W_MSDU_LENGTH_OFF 3 /* 7:0 of length, next byte 11:8 in top 4 bits */
482 #define vVW510021_W_BVCV_VALID_OFF 4 /* BV,CV Determine validity of bssid and txpower */
483 #define vVW510021_W_VCID_OFF 6 /* offset of VC (client) ID */
484 #define vVW510021_W_PLCP_LENGTH_OFF 12 /* LENGTH field in the plcp header */
486 /* Masks and defines */
487 #define vVW510021_W_IS_BV 0x04 /* BV bit in STATS block */
488 #define vVW510021_W_IS_CV 0x02 /* BV bit in STATS block */
489 #define vVW510021_W_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else 0) */
490 #define vVW510021_W_QOS_VALID 0x4000
491 #define vVW510021_W_HT_VALID 0x2000
492 #define vVW510021_W_L4ID_VALID 0x1000
493 #define vVW510021_W_MCS_MASK 0x3f /* mcs index (a/b) type mask */
494 #define vVW510021_W_MOD_SCHEME_MASK 0x3f /* modulation type mask */
495 #define vVW510021_W_PLCPC_MASK 0x03 /* PLPCP type mask */
496 #define vVW510021_W_SEL_MASK 0x80
497 #define vVW510021_W_WEP_MASK 0x0001
498 #define vVW510021_W_CBW_MASK 0xC0
500 #define vVW510024_W_VCID_MASK 0x03ff /* VC ID is only 10 bits */
502 #define vVW510021_W_MT_SEL_LEGACY 0x00
504 #define vVW510021_W_IS_WEP 0x0001
506 /* L1p byte 1 info */
508 /* Common to Series II and Series III */
510 #define vVW510021_W_IS_LONGPREAMBLE 0x40 /* short/long preamble bit */
511 #define vVW510021_W_IS_LONGGI 0x40 /* short/long guard interval bit */
516 * Pre-HT - contains rate index.
518 #define vVW510021_W_S2_RATE_INDEX(l1p_1) ((l1p_1) & 0x3f) /* rate index for pre-HT */
521 * HT - contains MCS index.
523 * XXX - MCS indices for HT go up to 76, which doesn't fit in 6 bits;
524 * either the mask is wrong, or the hardware can't receive packets
525 * with an MCS of 64 through 76, or the hardware can but misreports
528 #define vVW510021_W_S2_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
531 * VHT - contains MCS index and number of spatial streams.
532 * The number of spatial streams from the FPGA is zero-based, so we add
535 #define vVW510021_W_S2_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index for VHT */
536 #define vVW510021_W_S2_NSS_VHT(l1p_1) (((l1p_1) >> 4) + 1) /* NSS */
541 * Pre-HT - contains rate index.
543 #define vVW510021_W_S3_RATE_INDEX(l1p_1) ((l1p_1) & 0x3f)
546 * HT - contains MCS index.
548 * XXX - MCS indices for HT go up to 76, which doesn't fit in 6 bits;
549 * either the mask is wrong, or the hardware can't receive packets
550 * with an MCS of 64 through 76, or the hardware can but misreports
553 #define vVW510021_W_S3_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
556 * VHT - contains MCS index and number of spatial streams.
557 * The number of spatial streams from the FPGA is zero-based, so we add
560 #define vVW510021_W_S3_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index */
561 #define vVW510021_W_S3_NSS_VHT(l1p_1) ((((l1p_1) >> 4) & 0x03) + 1) /* NSS */
563 /* L1p byte 2 info */
565 /* Common to Series II and Series III */
566 #define vVW510021_W_BANDWIDTH_VHT(l1p_2) (((l1p_2) >> 4) & 0xf)
567 /* 3 = 40 MHz, 4 = 80 MHz; what about 20 and 160 MHz? */
570 #define vVW510021_W_S2_PLCP_TYPE(l1p_2) ((l1p_2) & 0x03) /* PLCP type */
573 #define vVW510021_W_S3_PLCP_TYPE(l1p_2) ((l1p_2) & 0x0f) /* PLCP type */
576 #define vVW510021_W_PLCP_LEGACY 0x00 /* pre-HT (11b/a/g) */
577 #define vVW510021_W_PLCP_MIXED 0x01 /* HT, mixed (11n) */
578 #define vVW510021_W_PLCP_GREENFIELD 0x02 /* HT, greenfield (11n) */
579 #define vVW510021_W_PLCP_VHT_MIXED 0x03 /* VHT (11ac) */
581 /* Bits in FRAME_TYPE field */
582 #define vVW510021_W_IS_TCP 0x01000000 /* TCP */
583 #define vVW510021_W_IS_UDP 0x00100000 /* UDP */
584 #define vVW510021_W_IS_ICMP 0x00001000 /* ICMP */
585 #define vVW510021_W_IS_IGMP 0x00010000 /* IGMP */
587 #define vVW510021_W_HEADER_VERSION 0x00
588 #define vVW510021_W_DEVICE_TYPE 0x15
589 #define vVW510021_W_11n_DEVICE_TYPE 0x20
590 #define S2_W_FPGA_VERSION 0x000C
591 #define vVW510021_W_11n_FPGA_VERSION 0x000D
594 #define vVW510021_W_FCS_ERROR 0x01
596 #define vVW510021_W_CRYPTO_ERROR 0x50000
598 #define vVW510021_W_WEPTYPE 0x0001 /* WEP frame */
599 #define vVW510021_W_TKIPTYPE 0x0002 /* TKIP frame */
600 #define vVW510021_W_CCMPTYPE 0x0004 /* CCMP frame */
602 /* definitions for VW510024 FPGA, wired ethernet format */
605 52 bytes of stats block trailer
607 /* offsets in the stats block */
608 #define vVW510024_E_STATS_LEN 48 /* length of stats block trailer */
609 #define vVW510024_E_MSDU_LENGTH_OFF 0 /* MSDU 16 BITS */
610 #define vVW510024_E_BMCV_VALID_OFF 2 /* BM,CV Determine validITY */
611 #define vVW510024_E_VCID_OFF 2 /* offset of VC (client) ID 13:8, */
613 #define vVW510024_E_STARTT_OFF 4 /* offset of start time, 64 bits */
614 #define vVW510024_E_ENDT_OFF 12 /* offset of end time, 64 bits */
615 #define vVW510024_E_ERRORS_OFF 22 /* offset of error vector */
616 #define vVW510024_E_VALID_OFF 24 /* 2 Bytes with different validity bits */
617 #define vVW510024_E_INFO_OFF 26 /* offset of INFO field, 16 LSBs */
618 #define vVW510024_E_FRAME_TYPE_OFF 28
619 #define vVW510024_E_L4ID_OFF 32
620 #define vVW510024_E_IPLEN_OFF 34
621 #define vVW510024_E_FLOWSEQ_OFF 36 /* offset of signature sequence number */
622 #define vVW510024_E_FLOWID_OFF 37 /* offset of flow ID */
623 #define vVW510024_E_LATVAL_OFF 40 /* offset of delay/flowtimestamp, 32 bits */
624 #define vVW510024_E_FPGA_VERSION_OFF 20 /* offset of fpga version, 16 bits */
625 #define vVW510024_E_MATCH_OFF 51 /* offset of pattern match vector */
627 /* offsets in the header block */
628 #define vVW510024_E_HEADER_LEN vVW510021_W_HEADER_LEN /* length of FRAME header */
629 #define vVW510024_E_RXTX_OFF vVW510021_W_RXTX_OFF /* rxtx offset, cmd byte */
630 #define vVW510024_E_HEADER_VERSION_OFF 16 /* version, 2bytes */
631 #define vVW510024_E_MSG_LENGTH_OFF vVW510021_MSG_LENGTH_OFF /* MSG LENGTH, 2bytes */
632 #define vVW510024_E_DEVICE_TYPE_OFF vVW510021_W_DEVICE_TYPE_OFF /* Device Type, 2bytes */
634 /* Masks and defines */
635 #define vVW510024_E_IS_BV 0x80 /* Bm bit in STATS block */
636 #define vVW510024_E_IS_CV 0x40 /* cV bit in STATS block */
637 #define vVW510024_E_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else force to 0) */
638 #define vVW510024_E_QOS_VALID 0x0000 /** not valid for ethernet **/
639 #define vVW510024_E_L4ID_VALID 0x1000
640 #define vVW510024_E_CBW_MASK 0xC0
641 #define vVW510024_E_VCID_MASK 0x3FFF /* VCID is only 14 bits */
643 #define vVW510024_E_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
644 #define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
645 #define vVW510024_E_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
646 #define vVW510024_E_IS_IGMP 0x00010000
647 #define vVW510024_E_IS_VLAN 0x00004000
649 #define vVW510024_E_HEADER_VERSION 0x00
650 #define vVW510024_E_DEVICE_TYPE 0x18
651 #define vVW510024_E_FPGA_VERSION 0x0001
653 #define FPGA_VER_NOT_APPLICABLE 0
655 #define UNKNOWN_FPGA 0
658 #define vVW510012_E_FPGA 3
659 #define vVW510024_E_FPGA 4
662 /* the flow signature is:
664 0 Magic Number (0xDD)
665 1 Chassis Number[7:0]
671 7 Flow Sequence Number[7:0]
682 #define SIG_SIZE 16 /* size of signature field, bytes */
683 #define SIG_FID_OFF 4 /* offset of flow ID in signature */
684 #define SIG_FSQ_OFF 7 /* offset of flow seqnum in signature */
685 #define SIG_TS_OFF 8 /* offset of flow seqnum in signature */
689 /*--------------------------------------------------------------------------------------*/
690 /* Per-capture file private data structure */
693 /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
694 /* version number of .vwr file, and are set up by setup_defaults() */
695 uint32_t STATS_LEN
; /* length of stats block trailer */
696 uint32_t STATS_START_OFF
; /* STATS OFF AFTER HEADER */
697 uint32_t VALID_OFF
; /* bit 6 (0x40) is flow-is-valid flag */
698 uint32_t MTYPE_OFF
; /* offset of modulation type */
699 uint32_t VCID_OFF
; /* offset of VC ID */
700 uint32_t FLOWSEQ_OFF
; /* offset of signature sequence number */
701 uint32_t FLOWID_OFF
; /* offset of flow ID */
702 uint32_t OCTET_OFF
; /* offset of octets */
703 uint32_t ERRORS_OFF
; /* offset of error vector */
704 uint32_t PATN_OFF
; /* offset of pattern match vector */
705 uint32_t RSSI_OFF
; /* RSSI (NOTE: RSSI must be negated!) */
706 uint32_t STARTT_OFF
; /* offset of start time, 64 bits */
707 uint32_t ENDT_OFF
; /* offset of end time, 64 bits */
708 uint32_t LATVAL_OFF
; /* offset of latency, 32 bits */
709 uint32_t INFO_OFF
; /* offset of INFO field, 16 bits */
710 uint32_t L1P_1_OFF
; /* offset 1ST Byte of l1params */
711 uint32_t L1P_2_OFF
; /* offset 2nd Byte of l1params */
712 uint32_t L4ID_OFF
; /* LAYER 4 id offset*/
713 uint32_t IPLEN_OFF
; /* */
714 uint32_t PLCP_LENGTH_OFF
; /* offset of length field in the PLCP header */
715 uint32_t FPGA_VERSION_OFF
; /* offset of fpga version field, 16 bits */
716 uint32_t HEADER_VERSION_OFF
; /* offset of header version, 16 bits */
717 uint32_t RXTX_OFF
; /* offset of CMD bit, rx or tx */
718 uint32_t FRAME_TYPE_OFF
;
720 /* other information about the file in question */
721 uint32_t MT_10_HALF
; /* 10 Mb/s half-duplex */
722 uint32_t MT_10_FULL
; /* 10 Mb/s full-duplex */
723 uint32_t MT_100_HALF
; /* 100 Mb/s half-duplex */
724 uint32_t MT_100_FULL
; /* 100 Mb/s full-duplex */
725 uint32_t MT_1G_HALF
; /* 1 Gb/s half-duplex */
726 uint32_t MT_1G_FULL
; /* 1 Gb/s full-duplex */
727 uint32_t FCS_ERROR
; /* FCS error in frame */
728 uint32_t CRYPTO_ERR
; /* RX decrypt error flags */
729 uint32_t PAYCHK_ERR
; /* payload checksum failure */
730 uint32_t RETRY_ERR
; /* excessive retries on TX failure */
731 uint8_t IS_RX
; /* TX/RX bit in STATS block */
732 uint8_t MT_MASK
; /* modulation type mask */
733 uint16_t VCID_MASK
; /* VC ID might not be a full 16 bits */
734 uint32_t FLOW_VALID
; /* flow-is-valid flag (else force to 0) */
736 uint32_t RX_DECRYPTS
; /* RX-frame-was-decrypted bits */
737 uint32_t TX_DECRYPTS
; /* TX-frame-was-decrypted bits */
738 uint32_t FC_PROT_BIT
; /* Protected Frame bit in FC1 of frame */
739 uint32_t MT_CCKL
; /* CCK modulation, long preamble */
740 uint32_t MT_CCKS
; /* CCK modulation, short preamble */
741 uint32_t MT_OFDM
; /* OFDM modulation */
742 uint32_t MCS_INDEX_MASK
; /* mcs index type mask */
743 uint32_t FPGA_VERSION
;
744 uint32_t WEPTYPE
; /* frame is WEP */
745 uint32_t TKIPTYPE
; /* frame is TKIP */
746 uint32_t CCMPTYPE
; /* frame is CCMP */
754 uint32_t OCTO_VERSION
;
758 * NSS for various MCS values.
760 #define MAX_HT_MCS 76
761 static unsigned nss_for_mcs
[MAX_HT_MCS
+1] = {
762 1, 1, 1, 1, 1, 1, 1, 1, /* 0-7 */
763 2, 2, 2, 2, 2, 2, 2, 2, /* 8-15 */
764 3, 3, 3, 3, 3, 3, 3, 3, /* 16-23 */
765 4, 4, 4, 4, 4, 4, 4, 4, /* 24-31 */
767 2, 2, 2, 2, 2, 2, /* 33-38 */
768 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 39-52 */
769 4, 4, 4, 4, 4, 4, /* 53-58 */
770 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 /* 59-76 */
773 /* internal utility functions */
774 static int decode_msg(vwr_t
*vwr
, register uint8_t *, int *, int *, int *);
775 static uint8_t get_ofdm_rate(const uint8_t *);
776 static uint8_t get_cck_rate(const uint8_t *plcp
);
777 static void setup_defaults(vwr_t
*, uint16_t);
779 static bool vwr_read(wtap
*, wtap_rec
*, int *, char **, int64_t *);
780 static bool vwr_seek_read(wtap
*, int64_t, wtap_rec
*, int *, char **);
782 static bool vwr_read_rec_header(vwr_t
*, FILE_T
, int *, int *, int *,
784 static bool vwr_process_rec_data(FILE_T fh
, int rec_size
,
785 wtap_rec
*record
, vwr_t
*vwr
,
786 int IS_TX
, int log_mode
, int *err
,
789 static int vwr_get_fpga_version(wtap
*, int *, char **);
791 static bool vwr_read_s1_W_rec(vwr_t
*, wtap_rec
*, const uint8_t *,
792 int, int *, char **);
793 static bool vwr_read_s2_W_rec(vwr_t
*, wtap_rec
*, const uint8_t *,
794 int, int, int *, char **);
795 /* For FPGA version >= 48 (OCTO Platform), following function will be used */
796 static bool vwr_read_s3_W_rec(vwr_t
*, wtap_rec
*, const uint8_t *,
797 int, int, int, int *, char **);
798 static bool vwr_read_rec_data_ethernet(vwr_t
*, wtap_rec
*,
799 const uint8_t *, int,
800 int, int *, char **);
802 static int find_signature(const uint8_t *, int, int, register uint32_t, register uint8_t);
803 static uint64_t get_signature_ts(const uint8_t *, int, int);
804 static float get_legacy_rate(uint8_t);
805 static float get_ht_rate(uint8_t, uint16_t);
806 static float get_vht_rate(uint8_t, uint16_t, uint8_t);
808 static int vwr_80211_file_type_subtype
= -1;
809 static int vwr_eth_file_type_subtype
= -1;
811 void register_vwr(void);
813 /* Open a .vwr file for reading */
814 /* This does very little, except setting the wiretap header for a VWR file type */
815 /* and setting the timestamp precision to microseconds. */
817 wtap_open_return_val
vwr_open(wtap
*wth
, int *err
, char **err_info
)
824 fpgaVer
= vwr_get_fpga_version(wth
, err
, err_info
);
826 return WTAP_OPEN_ERROR
; /* I/O error */
828 if (fpgaVer
== UNKNOWN_FPGA
) {
829 return WTAP_OPEN_NOT_MINE
; /* not a VWR file */
832 /* This is a vwr file */
833 vwr
= g_new0(vwr_t
, 1);
834 wth
->priv
= (void *)vwr
;
836 vwr
->FPGA_VERSION
= fpgaVer
;
837 /* set the local module options first */
838 setup_defaults(vwr
, fpgaVer
);
840 wth
->snapshot_length
= 0;
841 wth
->subtype_read
= vwr_read
;
842 wth
->subtype_seek_read
= vwr_seek_read
;
843 wth
->file_tsprec
= WTAP_TSPREC_USEC
;
844 wth
->file_encap
= WTAP_ENCAP_IXVERIWAVE
;
846 if (fpgaVer
== S2_W_FPGA
|| fpgaVer
== S1_W_FPGA
|| fpgaVer
== S3_W_FPGA
)
847 wth
->file_type_subtype
= vwr_80211_file_type_subtype
;
848 else if (fpgaVer
== vVW510012_E_FPGA
|| fpgaVer
== vVW510024_E_FPGA
)
849 wth
->file_type_subtype
= vwr_eth_file_type_subtype
;
852 * Add an IDB; we don't know how many interfaces were
853 * involved, so we just say one interface, about which
854 * we only know the link-layer type, snapshot length,
855 * and time stamp resolution.
857 wtap_add_generated_idb(wth
);
859 return WTAP_OPEN_MINE
;
863 /* Read the next packet */
864 /* Note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
865 /* different types; some types, including frame record headers, are followed by */
866 /* variable-length data. */
867 /* A frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
868 /* frame, and a 64-byte statistics block trailer. */
869 /* The PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
871 static bool vwr_read(wtap
*wth
, wtap_rec
*rec
, int *err
, char **err_info
,
872 int64_t *data_offset
)
874 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
875 int rec_size
= 0, IS_TX
= 0, log_mode
= 0;
877 /* read the next frame record header in the capture file; if no more frames, return */
878 if (!vwr_read_rec_header(vwr
, wth
->fh
, &rec_size
, &IS_TX
, &log_mode
, err
, err_info
))
879 return false; /* Read error or EOF */
882 * We're past the header; return the offset of the header, not of
883 * the data past the header.
885 *data_offset
= (file_tell(wth
->fh
) - VW_RECORD_HEADER_LENGTH
);
887 /* got a frame record; read and process it */
888 if (!vwr_process_rec_data(wth
->fh
, rec_size
, rec
, vwr
, IS_TX
, log_mode
,
895 /* read a random record in the middle of a file; the start of the record is @ seek_off */
897 static bool vwr_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*record
,
898 int *err
, char **err_info
)
900 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
901 int rec_size
, IS_TX
= 0, log_mode
= 0;
903 /* first seek to the indicated record header */
904 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
907 /* read in the record header */
908 if (!vwr_read_rec_header(vwr
, wth
->random_fh
, &rec_size
, &IS_TX
, &log_mode
, err
, err_info
))
909 return false; /* Read error or EOF */
911 return vwr_process_rec_data(wth
->random_fh
, rec_size
, record
, vwr
, IS_TX
,
912 log_mode
, err
, err_info
);
915 /* Scan down in the input capture file to find the next frame header. */
916 /* Decode and skip over all non-frame messages that are in the way. */
917 /* Return true on success, false on EOF or error. */
918 /* Also return the frame size in bytes and the "is transmitted frame" flag. */
920 static bool vwr_read_rec_header(vwr_t
*vwr
, FILE_T fh
, int *rec_size
, int *IS_TX
, int *log_mode
, int *err
, char **err_info
)
923 uint8_t header
[VW_RECORD_HEADER_LENGTH
];
927 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
928 /* or if we run out of data. */
929 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
930 /* variable-length item, we read the variable length item out and discard it. */
931 /* If we find a frame, we return (with the header in the passed buffer). */
933 if (!wtap_read_bytes_or_eof(fh
, header
, VW_RECORD_HEADER_LENGTH
, err
, err_info
))
936 /* Got a header; invoke decode-message function to parse and process it. */
937 /* If the function returns a length, then a frame or variable-length message */
938 /* follows the 16-byte message. */
939 /* If the variable length message is not a frame, simply skip over it. */
940 if ((f_len
= decode_msg(vwr
, header
, &v_type
, IS_TX
, log_mode
)) != 0) {
941 if (f_len
> B_SIZE
) {
942 *err
= WTAP_ERR_BAD_FILE
;
943 *err_info
= ws_strdup_printf("vwr: Invalid message record length %d", f_len
);
946 else if (v_type
!= VT_FRAME
) {
947 if (!wtap_read_bytes(fh
, NULL
, f_len
, err
, err_info
))
958 /* Figure out the FPGA version (and also see whether this is a VWR file type. */
959 /* Return FPGA version if it's a known version, UNKNOWN_FPGA if it's not, */
960 /* and -1 on an I/O error. */
962 static int vwr_get_fpga_version(wtap
*wth
, int *err
, char **err_info
)
964 uint8_t *rec
; /* local buffer (holds input record) */
965 uint8_t header
[VW_RECORD_HEADER_LENGTH
];
968 uint8_t *s_510006_ptr
= NULL
;
969 uint8_t *s_510024_ptr
= NULL
;
970 uint8_t *s_510012_ptr
= NULL
; /* stats pointers */
971 int64_t filePos
= -1;
972 uint64_t bytes_read
= 0;
973 uint32_t frame_type
= 0;
975 uint16_t data_length
= 0;
976 uint16_t fpga_version
;
977 bool valid_but_empty_file
= false;
979 filePos
= file_tell(wth
->fh
);
981 *err
= file_error(wth
->fh
, err_info
);
986 rec
= (uint8_t*)g_malloc(B_SIZE
);
987 /* Got a frame record; see if it is vwr */
988 /* If we don't get it all, then declare an error, we can't process the frame. */
989 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
990 /* or if we run out of data. */
991 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
992 /* variable-length item, we read the variable length item out and discard it. */
993 /* If we find a frame, we return (with the header in the passed buffer). */
994 while (wtap_read_bytes(wth
->fh
, header
, VW_RECORD_HEADER_LENGTH
, err
, err_info
)) {
995 /* Got a header; invoke decode-message function to parse and process it. */
996 /* If the function returns a length, then a frame or variable-length message */
997 /* follows the 16-byte message. */
998 /* If the variable length message is not a frame, simply skip over it. */
999 if ((f_len
= decode_msg(NULL
, header
, &v_type
, NULL
, NULL
)) != 0) {
1000 if (f_len
> B_SIZE
) {
1002 /* Treat this here as an indication that the file probably */
1003 /* isn't a vwr file. */
1004 return UNKNOWN_FPGA
;
1006 else if (v_type
!= VT_FRAME
) {
1007 if (!wtap_read_bytes(wth
->fh
, NULL
, f_len
, err
, err_info
)) {
1009 if (*err
== WTAP_ERR_SHORT_READ
)
1010 return UNKNOWN_FPGA
; /* short read - not a vwr file */
1013 else if (v_type
== VT_CPMSG
)
1014 valid_but_empty_file
= true;
1018 /* Got a frame record; read over entire record (frame + trailer) into a local buffer */
1019 /* If we don't get it all, assume this isn't a vwr file */
1020 if (!wtap_read_bytes(wth
->fh
, rec
, rec_size
, err
, err_info
)) {
1022 if (*err
== WTAP_ERR_SHORT_READ
)
1023 return UNKNOWN_FPGA
; /* short read - not a vwr file */
1027 /* I'll grab the bytes where the Ethernet "octets" field should be and the bytes where */
1028 /* the 802.11 "octets" field should be. Then if I do rec_size - octets - */
1029 /* size_of_stats_block and it's 0, I can select the correct type. */
1030 /* octets + stats_len = rec_size only when octets have been incremented to nearest */
1031 /* number divisible by 4. */
1033 /* First check for series I WLAN since the check is more rigorous. */
1034 if (rec_size
> v22_W_STATS_LEN
) {
1035 s_510006_ptr
= &(rec
[rec_size
- v22_W_STATS_LEN
]); /* point to 510006 WLAN */
1038 data_length
= pntoh16(&s_510006_ptr
[v22_W_OCTET_OFF
]);
1040 while (((data_length
+ i
) % 4) != 0)
1043 frame_type
= pntoh32(&s_510006_ptr
[v22_W_FRAME_TYPE_OFF
]);
1045 if (rec_size
== (data_length
+ v22_W_STATS_LEN
+ i
) && (frame_type
& v22_W_IS_80211
) == 0x1000000) {
1046 fpga_version
= S1_W_FPGA
;
1050 /* Next for the series I Ethernet */
1051 if ((rec_size
> v22_E_STATS_LEN
) && (fpga_version
== 1000)) {
1052 s_510012_ptr
= &(rec
[rec_size
- v22_E_STATS_LEN
]); /* point to 510012 enet */
1054 data_length
= pntoh16(&s_510012_ptr
[v22_E_OCTET_OFF
]);
1056 while (((data_length
+ i
) % 4) != 0)
1059 if (rec_size
== (data_length
+ v22_E_STATS_LEN
+ i
))
1060 fpga_version
= vVW510012_E_FPGA
;
1064 /* Next the series II WLAN */
1065 if ((rec_size
> vVW510021_W_STATS_TRAILER_LEN
) && (fpga_version
== 1000)) {
1068 if ((header
[8] == 48) || (header
[8] == 61) || (header
[8] == 68))
1069 fpga_version
= S3_W_FPGA
;
1071 data_length
= (256 * (rec
[vVW510021_W_MSDU_LENGTH_OFF
+ 1] & 0x1f)) + rec
[vVW510021_W_MSDU_LENGTH_OFF
];
1074 while (((data_length
+ i
) % 4) != 0)
1077 /*the 12 is from the 12 bytes of plcp header */
1078 if (rec_size
== (data_length
+ vVW510021_W_STATS_TRAILER_LEN
+vVW510021_W_AFTERHEADER_LEN
+12+i
))
1079 fpga_version
= S2_W_FPGA
;
1083 /* Finally the Series II Ethernet */
1084 if ((rec_size
> vVW510024_E_STATS_LEN
) && (fpga_version
== 1000)) {
1085 s_510024_ptr
= &(rec
[rec_size
- vVW510024_E_STATS_LEN
]); /* point to 510024 ENET */
1086 data_length
= pntoh16(&s_510024_ptr
[vVW510024_E_MSDU_LENGTH_OFF
]);
1089 while (((data_length
+ i
) % 4) != 0)
1092 if (rec_size
== (data_length
+ vVW510024_E_STATS_LEN
+ i
))
1093 fpga_version
= vVW510024_E_FPGA
;
1096 if (fpga_version
!= 1000)
1098 /* reset the file position offset */
1099 if (file_seek (wth
->fh
, filePos
, SEEK_SET
, err
) == -1) {
1104 /* We found an FPGA that works */
1106 return fpga_version
;
1110 bytes_read
+= VW_RECORD_HEADER_LENGTH
;
1111 if (bytes_read
> VW_BYTES_TO_CHECK
) {
1112 /* no frame found in VW_BYTES_TO_CHECK - not a vwr file */
1114 return UNKNOWN_FPGA
;
1118 /* Is this a valid but empty file? If so, claim it's the S3_W_FPGA FPGA. */
1119 if (valid_but_empty_file
) {
1124 if (*err
== WTAP_ERR_SHORT_READ
) {
1126 return UNKNOWN_FPGA
; /* short read - not a vwr file */
1136 /* Copy the actual packet data from the capture file into the target data block. */
1137 /* The packet is constructed as a 38-byte VeriWave metadata header plus the raw */
1140 static bool vwr_read_s1_W_rec(vwr_t
*vwr
, wtap_rec
*record
,
1141 const uint8_t *rec
, int rec_size
,
1142 int *err
, char **err_info
)
1145 int bytes_written
= 0; /* bytes output to buf so far */
1146 const uint8_t *s_ptr
, *m_ptr
; /* stats pointer */
1147 uint16_t msdu_length
, actual_octets
; /* octets in frame */
1148 uint16_t plcp_hdr_len
; /* PLCP header length */
1150 uint8_t m_type
; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
1152 uint64_t s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
1155 uint64_t start_time
, s_sec
, s_usec
= LL_ZERO
; /* start time, sec + usec */
1156 uint64_t end_time
; /* end time */
1157 uint32_t info
; /* INFO/ERRORS fields in stats blk */
1158 int8_t rssi
; /* RSSI, signed 8-bit number */
1159 int f_tx
; /* flag: if set, is a TX frame */
1160 uint8_t rate_index
; /* pre-HT only */
1161 uint16_t vc_id
, ht_len
=0; /* VC ID, total ip length */
1162 unsigned flow_id
; /* flow ID */
1163 uint32_t d_time
, errors
; /* packet duration & errors */
1164 int sig_off
, pay_off
; /* MAC+SNAP header len, signature offset */
1165 uint64_t sig_ts
; /* 32 LSBs of timestamp in signature */
1167 uint16_t vw_flags
; /* VeriWave-specific packet flags */
1170 * The record data must be large enough to hold the statistics trailer.
1172 if (rec_size
< v22_W_STATS_LEN
) {
1173 *err_info
= ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1174 rec_size
, v22_W_STATS_LEN
);
1175 *err
= WTAP_ERR_BAD_FILE
;
1179 /* Calculate the start of the statistics block in the buffer */
1180 /* Also get a bunch of fields from the stats block */
1181 s_ptr
= &(rec
[rec_size
- v22_W_STATS_LEN
]); /* point to it */
1182 m_type
= s_ptr
[v22_W_MTYPE_OFF
] & v22_E_MT_MASK
;
1183 f_tx
= !(s_ptr
[v22_W_MTYPE_OFF
] & v22_E_IS_RX
);
1184 actual_octets
= pntoh16(&s_ptr
[v22_W_OCTET_OFF
]);
1185 vc_id
= pntoh16(&s_ptr
[v22_W_VCID_OFF
]) & v22_E_VCID_MASK
;
1186 flow_seq
= s_ptr
[v22_W_FLOWSEQ_OFF
];
1188 latency
= (uint32_t)pcorey48tohll(&s_ptr
[v22_W_LATVAL_OFF
]);
1190 flow_id
= pntoh16(&s_ptr
[v22_W_FLOWID_OFF
+1]); /* only 16 LSBs kept */
1191 errors
= pntoh16(&s_ptr
[v22_W_ERRORS_OFF
]);
1193 info
= pntoh16(&s_ptr
[v22_W_INFO_OFF
]);
1194 rssi
= (s_ptr
[v22_W_RSSI_OFF
] & 0x80) ? (-1 * (s_ptr
[v22_W_RSSI_OFF
] & 0x7f)) : s_ptr
[v22_W_RSSI_OFF
];
1197 * Sanity check the octets field to determine if it's greater than
1198 * the packet data available in the record - i.e., the record size
1199 * minus the length of the statistics block.
1201 * Report an error if it is.
1203 if (actual_octets
> rec_size
- v22_W_STATS_LEN
) {
1204 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1206 *err
= WTAP_ERR_BAD_FILE
;
1210 /* Decode OFDM or CCK PLCP header and determine rate and short preamble flag. */
1211 /* The SIGNAL byte is always the first byte of the PLCP header in the frame. */
1212 if (m_type
== vwr
->MT_OFDM
)
1213 rate_index
= get_ofdm_rate(rec
);
1214 else if ((m_type
== vwr
->MT_CCKL
) || (m_type
== vwr
->MT_CCKS
))
1215 rate_index
= get_cck_rate(rec
);
1218 rflags
= (m_type
== vwr
->MT_CCKS
) ? FLAGS_SHORTPRE
: 0;
1219 /* Calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK. */
1220 /* Note that the number of octets in the frame also varies depending on OFDM/CCK, */
1221 /* because the PLCP header is prepended to the actual MPDU. */
1222 plcp_hdr_len
= (m_type
== vwr
->MT_OFDM
) ? 4 : 6;
1223 if (actual_octets
>= plcp_hdr_len
)
1224 actual_octets
-= plcp_hdr_len
;
1226 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header)",
1227 actual_octets
, plcp_hdr_len
);
1228 *err
= WTAP_ERR_BAD_FILE
;
1231 m_ptr
= &rec
[plcp_hdr_len
];
1232 msdu_length
= actual_octets
;
1235 * The MSDU length includes the FCS.
1237 * The packet data does *not* include the FCS - it's just 4 bytes
1238 * of junk - so we have to remove it.
1240 * We'll be stripping off that junk, so make sure we have at least
1241 * 4 octets worth of packet data.
1243 * There seems to be a special case of a length of 0.
1245 if (actual_octets
< 4) {
1246 if (actual_octets
!= 0) {
1247 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header and 4 bytes of FCS)",
1248 actual_octets
, plcp_hdr_len
);
1249 *err
= WTAP_ERR_BAD_FILE
;
1256 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1257 /* 64-bit times are "Corey-endian" */
1258 s_time
= pcoreytohll(&s_ptr
[v22_W_STARTT_OFF
]);
1259 e_time
= pcoreytohll(&s_ptr
[v22_W_ENDT_OFF
]);
1261 /* find the packet duration (difference between start and end times) */
1262 d_time
= (uint32_t)((e_time
- s_time
) / NS_IN_US
); /* find diff, converting to usec */
1264 /* also convert the packet start time to seconds and microseconds */
1265 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
1266 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
1267 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
1269 /* also convert the packet end time to seconds and microseconds */
1270 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
1272 /* extract the 32 LSBs of the signature timestamp field from the data block*/
1273 pay_off
= 42; /* 24 (MAC) + 8 (SNAP) + IP */
1274 sig_off
= find_signature(m_ptr
, rec_size
- 6, pay_off
, flow_id
, flow_seq
);
1275 if (m_ptr
[sig_off
] == 0xdd)
1276 sig_ts
= get_signature_ts(m_ptr
, sig_off
, rec_size
- v22_W_STATS_LEN
);
1281 * Fill up the per-packet header.
1283 * We include the length of the metadata headers in the packet lengths.
1285 * The maximum value of actual_octets is 8191, which, even after
1286 * adding the lengths of the metadata headers, is less than
1287 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1289 record
->rec_header
.packet_header
.len
= STATS_COMMON_FIELDS_LEN
+ EXT_WLAN_FIELDS_LEN
+ actual_octets
;
1290 record
->rec_header
.packet_header
.caplen
= STATS_COMMON_FIELDS_LEN
+ EXT_WLAN_FIELDS_LEN
+ actual_octets
;
1292 record
->ts
.secs
= (time_t)s_sec
;
1293 record
->ts
.nsecs
= (int)(s_usec
* 1000);
1294 record
->rec_header
.packet_header
.pkt_encap
= WTAP_ENCAP_IXVERIWAVE
;
1296 record
->rec_type
= REC_TYPE_PACKET
;
1297 record
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
1298 record
->presence_flags
= WTAP_HAS_TS
;
1300 ws_buffer_assure_space(&record
->data
, record
->rec_header
.packet_header
.caplen
);
1301 data_ptr
= ws_buffer_start_ptr(&record
->data
);
1304 * Generate and copy out the common metadata headers,
1305 * set the port type to 0 (WLAN).
1307 * All values are copied out in little-endian byte order.
1309 /* 1st octet of record for port_type and command (command is 0, hence RX) */
1310 phtole8(&data_ptr
[bytes_written
], WLAN_PORT
);
1312 /* 2nd octet of record for fpga version (0, hence pre-OCTO) */
1313 phtole8(&data_ptr
[bytes_written
], 0);
1316 phtoles(&data_ptr
[bytes_written
], STATS_COMMON_FIELDS_LEN
); /* it_len */
1318 phtoles(&data_ptr
[bytes_written
], msdu_length
);
1320 phtolel(&data_ptr
[bytes_written
], flow_id
);
1322 phtoles(&data_ptr
[bytes_written
], vc_id
);
1324 phtoles(&data_ptr
[bytes_written
], flow_seq
);
1326 if (!f_tx
&& sig_ts
!= 0) {
1327 phtolel(&data_ptr
[bytes_written
], latency
);
1329 phtolel(&data_ptr
[bytes_written
], 0);
1332 phtolel(&data_ptr
[bytes_written
], sig_ts
); /* 32 LSBs of signature timestamp (nsec) */
1334 phtolell(&data_ptr
[bytes_written
], start_time
); /* record start & end times of frame */
1336 phtolell(&data_ptr
[bytes_written
], end_time
);
1338 phtolel(&data_ptr
[bytes_written
], d_time
);
1342 * Generate and copy out the WLAN metadata headers.
1344 * All values are copied out in little-endian byte order.
1346 phtoles(&data_ptr
[bytes_written
], EXT_WLAN_FIELDS_LEN
);
1348 phtoles(&data_ptr
[bytes_written
], rflags
);
1350 if (m_type
== vwr
->MT_OFDM
) {
1351 phtoles(&data_ptr
[bytes_written
], CHAN_OFDM
);
1353 phtoles(&data_ptr
[bytes_written
], CHAN_CCK
);
1356 phyRate
= (uint16_t)(get_legacy_rate(rate_index
) * 10);
1357 phtoles(&data_ptr
[bytes_written
], phyRate
);
1359 data_ptr
[bytes_written
] = vVW510021_W_PLCP_LEGACY
; /* pre-HT */
1361 data_ptr
[bytes_written
] = rate_index
;
1363 data_ptr
[bytes_written
] = 1; /* pre-VHT, so NSS = 1 */
1365 data_ptr
[bytes_written
] = rssi
;
1367 /* antennae b, c, d signal power */
1368 data_ptr
[bytes_written
] = 100;
1370 data_ptr
[bytes_written
] = 100;
1372 data_ptr
[bytes_written
] = 100;
1375 data_ptr
[bytes_written
] = 0;
1378 /* fill in the VeriWave flags field */
1381 vw_flags
|= VW_FLAGS_TXF
;
1382 if (errors
& vwr
->FCS_ERROR
)
1383 vw_flags
|= VW_FLAGS_FCSERR
;
1384 if (!f_tx
&& (errors
& vwr
->CRYPTO_ERR
))
1385 vw_flags
|= VW_FLAGS_DCRERR
;
1386 if (!f_tx
&& (errors
& vwr
->RETRY_ERR
))
1387 vw_flags
|= VW_FLAGS_RETRERR
;
1388 if (info
& vwr
->WEPTYPE
)
1389 vw_flags
|= VW_FLAGS_IS_WEP
;
1390 else if (info
& vwr
->TKIPTYPE
)
1391 vw_flags
|= VW_FLAGS_IS_TKIP
;
1392 else if (info
& vwr
->CCMPTYPE
)
1393 vw_flags
|= VW_FLAGS_IS_CCMP
;
1394 phtoles(&data_ptr
[bytes_written
], vw_flags
);
1397 phtoles(&data_ptr
[bytes_written
], ht_len
);
1399 phtoles(&data_ptr
[bytes_written
], info
);
1401 phtolel(&data_ptr
[bytes_written
], errors
);
1405 * Finally, copy the whole MAC frame to the packet buffer as-is.
1406 * This does not include the PLCP; the MPDU starts at 4 or 6
1407 * depending on OFDM/CCK.
1408 * This also does not include the last 4 bytes, as those don't
1409 * contain an FCS, they just contain junk.
1411 memcpy(&data_ptr
[bytes_written
], &rec
[plcp_hdr_len
], actual_octets
);
1417 static bool vwr_read_s2_W_rec(vwr_t
*vwr
, wtap_rec
*record
,
1418 const uint8_t *rec
, int rec_size
,
1419 int IS_TX
, int *err
, char **err_info
)
1422 int bytes_written
= 0; /* bytes output to buf so far */
1423 const uint8_t *s_start_ptr
,*s_trail_ptr
, *plcp_ptr
, *m_ptr
; /* stats & MPDU ptr */
1424 uint32_t msdu_length
, actual_octets
; /* octets in frame */
1425 uint8_t l1p_1
, l1p_2
, plcp_type
, rate_mcs_index
, nss
; /* mod (CCK-L/CCK-S/OFDM) */
1427 uint64_t s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
1429 uint64_t latency
= LL_ZERO
;
1430 uint64_t start_time
, s_sec
, s_usec
= LL_ZERO
; /* start time, sec + usec */
1431 uint64_t end_time
; /* end time */
1432 uint16_t info
; /* INFO/ERRORS fields in stats blk */
1434 int8_t rssi
[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1435 int f_tx
; /* flag: if set, is a TX frame */
1436 uint16_t vc_id
, ht_len
=0; /* VC ID , total ip length*/
1437 uint32_t flow_id
, d_time
; /* flow ID, packet duration*/
1438 int sig_off
, pay_off
; /* MAC+SNAP header len, signature offset */
1439 uint64_t sig_ts
, tsid
; /* 32 LSBs of timestamp in signature */
1440 uint16_t chanflags
= 0; /* channel flags for WLAN metadata header */
1441 uint16_t radioflags
= 0; /* flags for WLAN metadata header */
1442 uint64_t delta_b
; /* Used for calculating latency */
1445 uint16_t vw_flags
; /* VeriWave-specific packet flags */
1448 * The record data must be large enough to hold the statistics header,
1449 * the PLCP, and the statistics trailer.
1451 if ((unsigned)rec_size
< vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
) {
1452 *err_info
= ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1454 vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
);
1455 *err
= WTAP_ERR_BAD_FILE
;
1459 /* Calculate the start of the statistics blocks in the buffer */
1460 /* Also get a bunch of fields from the stats blocks */
1461 s_start_ptr
= &(rec
[0]); /* point to stats header */
1462 s_trail_ptr
= &(rec
[rec_size
- vVW510021_W_STATS_TRAILER_LEN
]); /* point to stats trailer */
1464 l1p_1
= s_start_ptr
[vVW510021_W_L1P_1_OFF
];
1465 l1p_2
= s_start_ptr
[vVW510021_W_L1P_2_OFF
];
1466 plcp_type
= vVW510021_W_S2_PLCP_TYPE(l1p_2
);
1467 /* we do the range checks at the end before copying the values
1468 into the wtap header */
1469 msdu_length
= ((s_start_ptr
[vVW510021_W_MSDU_LENGTH_OFF
+1] & 0x1f) << 8)
1470 + s_start_ptr
[vVW510021_W_MSDU_LENGTH_OFF
];
1472 vc_id
= pntoh16(&s_start_ptr
[vVW510021_W_VCID_OFF
]);
1475 rssi
[0] = (s_start_ptr
[vVW510021_W_RSSI_TXPOWER_OFF
] & 0x80) ?
1476 -1 * (s_start_ptr
[vVW510021_W_RSSI_TXPOWER_OFF
] & 0x7f) :
1477 s_start_ptr
[vVW510021_W_RSSI_TXPOWER_OFF
] & 0x7f;
1481 rssi
[0] = (s_start_ptr
[vVW510021_W_RSSI_TXPOWER_OFF
] & 0x80) ?
1482 (s_start_ptr
[vVW510021_W_RSSI_TXPOWER_OFF
]- 256) :
1483 s_start_ptr
[vVW510021_W_RSSI_TXPOWER_OFF
];
1489 plcp_ptr
= &(rec
[8]);
1491 actual_octets
= msdu_length
;
1494 * Sanity check the octets field to determine if it's greater than
1495 * the packet data available in the record - i.e., the record size
1496 * minus the sum of (length of statistics header + PLCP) and
1497 * (length of statistics trailer).
1499 * Report an error if it is.
1501 if (actual_octets
> rec_size
- (vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
)) {
1502 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1504 *err
= WTAP_ERR_BAD_FILE
;
1509 flow_seq
= s_trail_ptr
[vVW510021_W_FLOWSEQ_OFF
];
1511 latency
= 0x00000000; /* clear latency */
1512 flow_id
= pntoh24(&s_trail_ptr
[vVW510021_W_FLOWID_OFF
]); /* all 24 bits valid */
1513 /* For tx latency is duration, for rx latency is timestamp */
1514 /* Get 48-bit latency value */
1515 tsid
= pcorey48tohll(&s_trail_ptr
[vVW510021_W_LATVAL_OFF
]);
1517 errors
= pntoh32(&s_trail_ptr
[vVW510021_W_ERRORS_OFF
]);
1518 info
= pntoh16(&s_trail_ptr
[vVW510021_W_INFO_OFF
]);
1519 if ((info
& v22_W_AGGREGATE_FLAGS
) != 0)
1520 /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
1521 ht_len
= pletoh16(&s_start_ptr
[vwr
->PLCP_LENGTH_OFF
]);
1524 /* decode OFDM or CCK PLCP header and determine rate and short preamble flag */
1525 /* the SIGNAL byte is always the first byte of the PLCP header in the frame */
1528 case vVW510021_W_PLCP_LEGACY
:
1530 * From IEEE Std 802.11-2012:
1532 * According to section 17.2.2 "PPDU format", the PLCP header
1533 * for the High Rate DSSS PHY (11b) has a SIGNAL field that's
1534 * 8 bits, followed by a SERVICE field that's 8 bits, followed
1535 * by a LENGTH field that's 16 bits, followed by a CRC field
1536 * that's 16 bits. The PSDU follows it. Section 17.2.3 "PPDU
1537 * field definitions" describes those fields.
1539 * According to sections 18.3.2 "PLCP frame format" and 18.3.4
1540 * "SIGNAL field", the PLCP for the OFDM PHY (11a) has a SIGNAL
1541 * field that's 24 bits, followed by a service field that's
1542 * 16 bits, followed by the PSDU. Section 18.3.5.2 "SERVICE
1543 * field" describes the SERVICE field.
1545 * According to section 19.3.2 "PPDU format", the frames for the
1546 * Extended Rate PHY (11g) either extend the 11b format, using
1547 * additional bits in the SERVICE field, or extend the 11a
1550 rate_mcs_index
= vVW510021_W_S2_RATE_INDEX(l1p_1
);
1551 if (rate_mcs_index
< 4) {
1552 chanflags
|= CHAN_CCK
;
1555 chanflags
|= CHAN_OFDM
;
1557 rate
= get_legacy_rate(rate_mcs_index
);
1561 case vVW510021_W_PLCP_MIXED
:
1563 * According to section 20.3.2 "PPDU format", the HT-mixed
1564 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
1565 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
1566 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
1569 * This means that the first octet of HT-SIG is at
1570 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
1572 * 0x80 is the CBW 20/40 bit of HT-SIG.
1574 /* set the appropriate flags to indicate HT mode and CB */
1575 rate_mcs_index
= vVW510021_W_S2_MCS_INDEX_HT(l1p_1
);
1576 radioflags
|= FLAGS_CHAN_HT
| ((plcp_ptr
[3] & 0x80) ? FLAGS_CHAN_40MHZ
: 0) |
1577 ((l1p_1
& vVW510021_W_IS_LONGGI
) ? 0 : FLAGS_CHAN_SHORTGI
);
1578 chanflags
|= CHAN_OFDM
;
1579 nss
= (rate_mcs_index
< MAX_HT_MCS
) ? nss_for_mcs
[rate_mcs_index
] : 0;
1580 rate
= get_ht_rate(rate_mcs_index
, radioflags
);
1583 case vVW510021_W_PLCP_GREENFIELD
:
1585 * According to section 20.3.2 "PPDU format", the HT-greenfield
1586 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
1589 * This means that the first octet of HT-SIG is at
1590 * plcp_ptr[0], as there's no L-SIG field to skip.
1592 * 0x80 is the CBW 20/40 bit of HT-SIG.
1594 /* set the appropriate flags to indicate HT mode and CB */
1595 rate_mcs_index
= vVW510021_W_S2_MCS_INDEX_HT(l1p_1
);
1596 radioflags
|= FLAGS_CHAN_HT
| ((plcp_ptr
[0] & 0x80) ? FLAGS_CHAN_40MHZ
: 0) |
1597 ((l1p_1
& vVW510021_W_IS_LONGGI
) ? 0 : FLAGS_CHAN_SHORTGI
);
1598 chanflags
|= CHAN_OFDM
;
1599 nss
= (rate_mcs_index
< MAX_HT_MCS
) ? nss_for_mcs
[rate_mcs_index
] : 0;
1600 rate
= get_ht_rate(rate_mcs_index
, radioflags
);
1603 case vVW510021_W_PLCP_VHT_MIXED
:
1605 * According to section 22.3.2 "VHT PPDU format" of IEEE Std
1606 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
1607 * (L-SIG), which looks like an 11a SIGNAL field, followed by
1608 * a VHT Signal A field (VHT-SIG-A) described in section
1609 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
1610 * between it and a VHT Signal B field (VHT-SIG-B) described
1611 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
1615 uint8_t SBW
= vVW510021_W_BANDWIDTH_VHT(l1p_2
);
1616 rate_mcs_index
= vVW510021_W_S2_MCS_INDEX_VHT(l1p_1
);
1617 radioflags
|= FLAGS_CHAN_VHT
| ((l1p_1
& vVW510021_W_IS_LONGGI
) ? 0 : FLAGS_CHAN_SHORTGI
);
1618 chanflags
|= CHAN_OFDM
;
1620 radioflags
|= FLAGS_CHAN_40MHZ
;
1622 radioflags
|= FLAGS_CHAN_80MHZ
;
1623 nss
= vVW510021_W_S2_NSS_VHT(l1p_1
);
1624 rate
= get_vht_rate(rate_mcs_index
, radioflags
, nss
);
1636 * The MSDU length includes the FCS.
1638 * The packet data does *not* include the FCS - it's just 4 bytes
1639 * of junk - so we have to remove it.
1641 * We'll be stripping off that junk, so make sure we have at least
1642 * 4 octets worth of packet data.
1644 * There seems to be a special case of a length of 0.
1646 if (actual_octets
< 4) {
1647 if (actual_octets
!= 0) {
1648 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
1650 *err
= WTAP_ERR_BAD_FILE
;
1657 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1658 /* 64-bit times are "Corey-endian" */
1659 s_time
= pcoreytohll(&s_trail_ptr
[vVW510021_W_STARTT_OFF
]);
1660 e_time
= pcoreytohll(&s_trail_ptr
[vVW510021_W_ENDT_OFF
]);
1662 /* find the packet duration (difference between start and end times) */
1663 d_time
= (uint32_t)((e_time
- s_time
) / NS_IN_US
); /* find diff, converting to usec */
1665 /* also convert the packet start time to seconds and microseconds */
1666 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
1667 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
1668 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
1670 /* also convert the packet end time to seconds and microseconds */
1671 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
1673 /* extract the 32 LSBs of the signature timestamp field */
1674 m_ptr
= &(rec
[8+12]);
1675 pay_off
= 42; /* 24 (MAC) + 8 (SNAP) + IP */
1676 sig_off
= find_signature(m_ptr
, rec_size
- 20, pay_off
, flow_id
, flow_seq
);
1677 if (m_ptr
[sig_off
] == 0xdd)
1678 sig_ts
= get_signature_ts(m_ptr
, sig_off
, rec_size
- vVW510021_W_STATS_TRAILER_LEN
);
1682 /* Set latency based on rx/tx and signature timestamp */
1684 if (tsid
< s_time
) {
1685 latency
= s_time
- tsid
;
1687 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1688 /* we look for a large difference between l_time and s_time. */
1689 delta_b
= tsid
- s_time
;
1690 if (delta_b
> 0x10000000)
1698 * Fill up the per-packet header.
1700 * We include the length of the metadata headers in the packet lengths.
1702 * The maximum value of actual_octets is 8191, which, even after
1703 * adding the lengths of the metadata headers, is less than
1704 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1706 record
->rec_header
.packet_header
.len
= STATS_COMMON_FIELDS_LEN
+ EXT_WLAN_FIELDS_LEN
+ actual_octets
;
1707 record
->rec_header
.packet_header
.caplen
= STATS_COMMON_FIELDS_LEN
+ EXT_WLAN_FIELDS_LEN
+ actual_octets
;
1709 record
->ts
.secs
= (time_t)s_sec
;
1710 record
->ts
.nsecs
= (int)(s_usec
* 1000);
1712 record
->rec_type
= REC_TYPE_PACKET
;
1713 record
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
1714 record
->presence_flags
= WTAP_HAS_TS
;
1716 ws_buffer_assure_space(&record
->data
, record
->rec_header
.packet_header
.caplen
);
1717 data_ptr
= ws_buffer_start_ptr(&record
->data
);
1720 * Generate and copy out the common metadata headers,
1721 * set the port type to 0 (WLAN).
1723 * All values are copied out in little-endian byte order.
1725 /*** msdu_length = msdu_length + 16; ***/
1726 /* 1st octet of record for port_type and command (command is 0, hence RX) */
1727 phtole8(&data_ptr
[bytes_written
], WLAN_PORT
);
1729 /* 2nd octet of record for fpga version (0, hence pre-OCTO) */
1730 phtole8(&data_ptr
[bytes_written
], 0);
1733 phtoles(&data_ptr
[bytes_written
], STATS_COMMON_FIELDS_LEN
); /* it_len */
1735 phtoles(&data_ptr
[bytes_written
], msdu_length
);
1737 phtolel(&data_ptr
[bytes_written
], flow_id
);
1739 phtoles(&data_ptr
[bytes_written
], vc_id
);
1741 phtoles(&data_ptr
[bytes_written
], flow_seq
);
1743 if (!f_tx
&& sig_ts
!= 0) {
1744 phtolel(&data_ptr
[bytes_written
], latency
);
1746 phtolel(&data_ptr
[bytes_written
], 0);
1749 phtolel(&data_ptr
[bytes_written
], sig_ts
); /* 32 LSBs of signature timestamp (nsec) */
1751 phtolell(&data_ptr
[bytes_written
], start_time
); /* record start & end times of frame */
1753 phtolell(&data_ptr
[bytes_written
], end_time
);
1755 phtolel(&data_ptr
[bytes_written
], d_time
);
1759 * Generate and copy out the WLAN metadata headers.
1761 * All values are copied out in little-endian byte order.
1763 phtoles(&data_ptr
[bytes_written
], EXT_WLAN_FIELDS_LEN
);
1765 if (info
& vVW510021_W_IS_WEP
)
1766 radioflags
|= FLAGS_WEP
;
1767 if (!(l1p_1
& vVW510021_W_IS_LONGPREAMBLE
) && (plcp_type
== vVW510021_W_PLCP_LEGACY
))
1768 radioflags
|= FLAGS_SHORTPRE
;
1769 phtoles(&data_ptr
[bytes_written
], radioflags
);
1771 phtoles(&data_ptr
[bytes_written
], chanflags
);
1773 phyRate
= (uint16_t)(rate
* 10);
1774 phtoles(&data_ptr
[bytes_written
], phyRate
);
1777 data_ptr
[bytes_written
] = plcp_type
;
1780 data_ptr
[bytes_written
] = rate_mcs_index
;
1783 data_ptr
[bytes_written
] = nss
;
1785 data_ptr
[bytes_written
] = rssi
[0];
1787 data_ptr
[bytes_written
] = rssi
[1];
1789 data_ptr
[bytes_written
] = rssi
[2];
1791 data_ptr
[bytes_written
] = rssi
[3];
1794 data_ptr
[bytes_written
] = 0;
1797 /* fill in the VeriWave flags field */
1800 vw_flags
|= VW_FLAGS_TXF
;
1801 if (errors
& 0x1f) /* If any error is flagged, then set the FCS error bit */
1802 vw_flags
|= VW_FLAGS_FCSERR
;
1803 if (!f_tx
&& (errors
& vwr
->CRYPTO_ERR
))
1804 vw_flags
|= VW_FLAGS_DCRERR
;
1805 if (!f_tx
&& (errors
& vwr
->RETRY_ERR
))
1806 vw_flags
|= VW_FLAGS_RETRERR
;
1807 if (info
& vwr
->WEPTYPE
)
1808 vw_flags
|= VW_FLAGS_IS_WEP
;
1809 else if (info
& vwr
->TKIPTYPE
)
1810 vw_flags
|= VW_FLAGS_IS_TKIP
;
1811 else if (info
& vwr
->CCMPTYPE
)
1812 vw_flags
|= VW_FLAGS_IS_CCMP
;
1813 phtoles(&data_ptr
[bytes_written
], vw_flags
);
1816 phtoles(&data_ptr
[bytes_written
], ht_len
);
1818 phtoles(&data_ptr
[bytes_written
], info
);
1820 phtolel(&data_ptr
[bytes_written
], errors
);
1823 /* Finally, copy the whole MAC frame to the packet buffer as-is.
1824 * This does not include the stats header or the PLCP.
1825 * This also does not include the last 4 bytes, as those don't
1826 * contain an FCS, they just contain junk.
1828 memcpy(&data_ptr
[bytes_written
], &rec
[vwr
->MPDU_OFF
], actual_octets
);
1833 static bool vwr_read_s3_W_rec(vwr_t
*vwr
, wtap_rec
*record
,
1834 const uint8_t *rec
, int rec_size
,
1835 int IS_TX
, int log_mode
, int *err
,
1839 int bytes_written
= 0; /* bytes output to buf so far */
1841 int stats_offset
= 0;
1842 const uint8_t *s_start_ptr
= NULL
,*s_trail_ptr
= NULL
, *plcp_ptr
, *m_ptr
; /* stats & MPDU ptr */
1843 uint32_t msdu_length
= 0, actual_octets
= 0; /* octets in frame */
1844 uint8_t l1p_1
= 0,l1p_2
= 0, plcp_type
, rate_mcs_index
, nss
; /* mod (CCK-L/CCK-S/OFDM) */
1845 uint64_t s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
1847 uint64_t latency
= LL_ZERO
;
1848 uint64_t start_time
= 0, s_sec
= 0, s_usec
= LL_ZERO
; /* start time, sec + usec */
1849 uint64_t end_time
= 0; /* end time */
1850 uint16_t info
= 0; /* INFO/ERRORS fields in stats blk */
1851 uint32_t errors
= 0;
1852 int8_t info_2nd
= 0,rssi
[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1854 uint32_t d_time
= 0, flow_id
= 0; /* packet duration, Flow Signature ID*/
1855 int sig_off
, pay_off
; /* MAC+SNAP header len, signature offset */
1856 uint64_t sig_ts
= 0, tsid
; /* 32 LSBs of timestamp in signature */
1857 uint64_t delta_b
; /* Used for calculating latency */
1858 uint8_t L1InfoC
= 0, port_type
, ver_fpga
= 0;
1859 uint8_t flow_seq
=0,plcp_hdr_flag
= 0,rf_id
= 0; /* indicates plcp hdr info */
1860 const uint8_t *rf_ptr
= NULL
;
1865 * The record data must be large enough to hold the statistics header,
1866 * the PLCP, and the statistics trailer.
1868 if (IS_TX
== 3) { /*IS_TX =3, i.e., command type is RF Modified*/
1869 if ((unsigned)rec_size
< OCTO_MODIFIED_RF_LEN
) {
1870 *err_info
= ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1872 OCTO_MODIFIED_RF_LEN
);
1873 *err
= WTAP_ERR_BAD_FILE
;
1880 * Fill up the per-packet header.
1882 * We include the length of the metadata headers in the packet lengths.
1884 * OCTO_MODIFIED_RF_LEN + 1 is less than WTAP_MAX_PACKET_SIZE_STANDARD will
1885 * ever be, so we don't need to check it.
1887 record
->rec_header
.packet_header
.len
= OCTO_MODIFIED_RF_LEN
+ 1; /* 1st octet is reserved for detecting type of frame while displaying in wireshark */
1888 record
->rec_header
.packet_header
.caplen
= OCTO_MODIFIED_RF_LEN
+ 1;
1890 record
->ts
.secs
= (time_t)s_sec
;
1891 record
->ts
.nsecs
= (int)(s_usec
* 1000);
1893 record
->rec_type
= REC_TYPE_PACKET
;
1894 record
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
1895 record
->presence_flags
= WTAP_HAS_TS
;
1897 ws_buffer_assure_space(&record
->data
, record
->rec_header
.packet_header
.caplen
);
1898 data_ptr
= ws_buffer_start_ptr(&record
->data
);
1900 port_type
= IS_TX
<< 4;
1906 /* Calculate the start of the statistics blocks in the buffer */
1907 /* Also get a bunch of fields from the stats blocks */
1908 /* 'stats_offset' variable is use to locate the exact offset.
1909 * When a RX frame contrains RF,
1910 * the position of Stats, Layer 1-4, PLCP parameters are shifted to
1911 * + OCTO_RF_MOD_ACTUAL_LEN bytes
1913 if (IS_TX
== 4) /*IS_TX =4, i.e., command type is RF-RX Modified*/
1915 stats_offset
= OCTO_RF_MOD_ACTUAL_LEN
;
1916 if ((unsigned)rec_size
< stats_offset
+ vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
) {
1917 *err_info
= ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1919 stats_offset
+ vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
);
1920 *err
= WTAP_ERR_BAD_FILE
;
1929 if ((unsigned)rec_size
< vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
) {
1930 *err_info
= ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1932 vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
);
1933 *err
= WTAP_ERR_BAD_FILE
;
1938 s_start_ptr
= &(rec
[stats_offset
]); /* point to stats header */
1939 s_trail_ptr
= &(rec
[rec_size
- vVW510021_W_STATS_TRAILER_LEN
] ); /* point to stats trailer */
1941 l1p_1
= s_start_ptr
[vVW510021_W_L1P_1_OFF
];
1942 l1p_2
= s_start_ptr
[vVW510021_W_L1P_2_OFF
];
1944 plcp_type
= vVW510021_W_S3_PLCP_TYPE(l1p_2
);
1947 case vVW510021_W_PLCP_LEGACY
:
1949 rate_mcs_index
= vVW510021_W_S3_RATE_INDEX(l1p_1
);
1953 case vVW510021_W_PLCP_MIXED
:
1954 case vVW510021_W_PLCP_GREENFIELD
:
1955 rate_mcs_index
= vVW510021_W_S3_MCS_INDEX_HT(l1p_1
);
1956 nss
= (rate_mcs_index
< MAX_HT_MCS
) ? nss_for_mcs
[rate_mcs_index
] : 0;
1959 case vVW510021_W_PLCP_VHT_MIXED
:
1960 rate_mcs_index
= vVW510021_W_S3_MCS_INDEX_VHT(l1p_1
);
1961 nss
= vVW510021_W_S3_NSS_VHT(l1p_1
);
1972 for (i
= 0; i
< 4; i
++)
1976 rssi
[i
] = (s_start_ptr
[4+i
] & 0x80) ? -1 * (s_start_ptr
[4+i
] & 0x7f) : s_start_ptr
[4+i
] & 0x7f;
1980 rssi
[i
] = (s_start_ptr
[4+i
] >= 128) ? (s_start_ptr
[4+i
] - 256) : s_start_ptr
[4+i
];
1984 if (IS_TX
== 0 || IS_TX
== 4){
1985 L1InfoC
= s_start_ptr
[8];
1988 msdu_length
= pntoh24(&s_start_ptr
[9]);
1990 /*** 16 bytes of PLCP header + 1 byte of L1P for user position ***/
1991 plcp_ptr
= &(rec
[stats_offset
+16]);
1993 /*** Add the PLCP length for S3_W_FPGA version VHT frames for Beamforming decode ***/
1994 if (log_mode
== 3) {
1995 frame_size
= rec_size
- (stats_offset
+ vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
);
1996 if (frame_size
> ((int) msdu_length
))
1997 actual_octets
= msdu_length
;
2000 * XXX - does this mean "the packet was cut short during
2001 * capture" or "this is a malformed record"?
2003 actual_octets
= frame_size
;
2008 actual_octets
= msdu_length
;
2011 * Sanity check the octets field to determine if it's greater than
2012 * the packet data available in the record - i.e., the record size
2013 * minus the sum of (length of statistics header + PLCP) and
2014 * (length of statistics trailer).
2016 * Report an error if it is.
2018 if (actual_octets
> rec_size
- (stats_offset
+ vwr
->MPDU_OFF
+ vVW510021_W_STATS_TRAILER_LEN
)) {
2019 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
2021 *err
= WTAP_ERR_BAD_FILE
;
2025 flow_seq
= s_trail_ptr
[vVW510021_W_FLOWSEQ_OFF
];
2027 latency
= 0x00000000; /* clear latency */
2028 flow_id
= pntoh24(&s_trail_ptr
[vVW510021_W_FLOWID_OFF
]); /* all 24 bits valid */
2029 /* For tx latency is duration, for rx latency is timestamp */
2030 /* Get 48-bit latency value */
2031 tsid
= pcorey48tohll(&s_trail_ptr
[vVW510021_W_LATVAL_OFF
]);
2033 errors
= pntoh32(&s_trail_ptr
[vVW510021_W_ERRORS_OFF
]);
2034 info
= pntoh16(&s_trail_ptr
[vVW510021_W_INFO_OFF
]);
2036 if (IS_TX
== 0 || IS_TX
== 4)
2037 info_2nd
= s_trail_ptr
[41];
2039 /*** Calculate Data rate based on
2040 * PLCP type, MCS index and number of spatial stream
2041 * radioflags is temporarily calculated, which is used in
2042 * get_ht_rate() and get_vht_rate().
2046 case vVW510021_W_PLCP_LEGACY
:
2047 rate
= get_legacy_rate(rate_mcs_index
);
2050 case vVW510021_W_PLCP_MIXED
:
2052 * According to section 20.3.2 "PPDU format", the HT-mixed
2053 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
2054 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
2055 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
2058 * This means that the first octet of HT-SIG is at
2059 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
2061 * 0x80 is the CBW 20/40 bit of HT-SIG.
2064 /* set the appropriate flags to indicate HT mode and CB */
2065 uint16_t radioflags
= FLAGS_CHAN_HT
| ((plcp_ptr
[3] & 0x80) ? FLAGS_CHAN_40MHZ
: 0) |
2066 ((l1p_1
& vVW510021_W_IS_LONGGI
) ? 0 : FLAGS_CHAN_SHORTGI
);
2067 rate
= get_ht_rate(rate_mcs_index
, radioflags
);
2071 case vVW510021_W_PLCP_GREENFIELD
:
2073 * According to section 20.3.2 "PPDU format", the HT-greenfield
2074 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
2077 * This means that the first octet of HT-SIG is at
2078 * plcp_ptr[0], as there's no L-SIG field to skip.
2080 * 0x80 is the CBW 20/40 bit of HT-SIG.
2083 /* set the appropriate flags to indicate HT mode and CB */
2084 uint16_t radioflags
= FLAGS_CHAN_HT
| ((plcp_ptr
[0] & 0x80) ? FLAGS_CHAN_40MHZ
: 0) |
2085 ((l1p_1
& vVW510021_W_IS_LONGGI
) ? 0 : FLAGS_CHAN_SHORTGI
);
2086 rate
= get_ht_rate(rate_mcs_index
, radioflags
);
2090 case vVW510021_W_PLCP_VHT_MIXED
:
2092 * According to section 22.3.2 "VHT PPDU format" of IEEE Std
2093 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
2094 * (L-SIG), which looks like an 11a SIGNAL field, followed by
2095 * a VHT Signal A field (VHT-SIG-A) described in section
2096 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
2097 * between it and a VHT Signal B field (VHT-SIG-B) described
2098 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
2102 uint8_t SBW
= vVW510021_W_BANDWIDTH_VHT(l1p_2
);
2103 uint16_t radioflags
= FLAGS_CHAN_VHT
| ((l1p_1
& vVW510021_W_IS_LONGGI
) ? 0 : FLAGS_CHAN_SHORTGI
);
2105 radioflags
|= FLAGS_CHAN_40MHZ
;
2107 radioflags
|= FLAGS_CHAN_80MHZ
;
2108 rate
= get_vht_rate(rate_mcs_index
, radioflags
, nss
);
2116 phyRate
= (uint16_t)(rate
* 10);
2117 /* Calculation of Data rate ends*/
2119 /* 'ver_fpga' is the 2nd Octet of each frame.
2120 * msb/lsb nibble indicates log mode/fpga version respectively.
2121 * where log mode = 0 is normal capture and 1 is reduced capture,
2122 * lsb nibble is set to 1 always as this function is applicable for only FPGA version >= 48
2124 if (log_mode
== 3) {
2125 if (frame_size
>= (int) msdu_length
) {
2127 * The MSDU length includes the FCS.
2129 * The packet data does *not* include the FCS - it's just 4
2130 * bytes of junk - so we have to remove it.
2132 * We'll be stripping off that junk, so make sure we have at
2133 * least 4 octets worth of packet data.
2135 * XXX - is the FCS actually present here, as it appears to be
2136 * if log_mode isn't 3?
2138 * There seems to be a special case of a length of 0.
2140 if (actual_octets
< 4) {
2141 if (actual_octets
!= 0) {
2142 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
2144 *err
= WTAP_ERR_BAD_FILE
;
2156 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
2157 /* 64-bit times are "Corey-endian" */
2158 s_time
= pcoreytohll(&s_trail_ptr
[vVW510021_W_STARTT_OFF
]);
2159 e_time
= pcoreytohll(&s_trail_ptr
[vVW510021_W_ENDT_OFF
]);
2161 /* find the packet duration (difference between start and end times) */
2162 d_time
= (uint32_t)((e_time
- s_time
) / NS_IN_US
); /* find diff, converting to usec */
2164 /* also convert the packet start time to seconds and microseconds */
2165 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
2166 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
2167 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
2169 /* also convert the packet end time to seconds and microseconds */
2170 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
2172 /* extract the 32 LSBs of the signature timestamp field */
2173 int m_ptr_offset
= stats_offset
+ 8 + 12;
2174 m_ptr
= rec
+ m_ptr_offset
;
2175 pay_off
= 42; /* 24 (MAC) + 8 (SNAP) + IP */
2176 sig_off
= find_signature(m_ptr
, rec_size
- m_ptr_offset
, pay_off
, flow_id
, flow_seq
);
2177 if (m_ptr
[sig_off
] == 0xdd)
2178 sig_ts
= get_signature_ts(m_ptr
, sig_off
, rec_size
- vVW510021_W_STATS_TRAILER_LEN
);
2182 /* Set latency based on rx/tx and signature timestamp */
2183 if (IS_TX
== 0 || IS_TX
== 4) {
2184 if (tsid
< s_time
) {
2185 latency
= s_time
- tsid
;
2187 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
2188 /* we look for a large difference between l_time and s_time. */
2189 delta_b
= tsid
- s_time
;
2190 if (delta_b
> 0x10000000)
2197 port_type
= IS_TX
<< 4;
2200 * Fill up the per-packet header.
2202 * We include the length of the metadata headers in the packet lengths.
2205 record
->rec_header
.packet_header
.len
= OCTO_MODIFIED_RF_LEN
+ OCTO_TIMESTAMP_FIELDS_LEN
+ OCTO_LAYER1TO4_LEN
+ actual_octets
;
2206 record
->rec_header
.packet_header
.caplen
= OCTO_MODIFIED_RF_LEN
+ OCTO_TIMESTAMP_FIELDS_LEN
+ OCTO_LAYER1TO4_LEN
+ actual_octets
;
2208 record
->rec_header
.packet_header
.len
= OCTO_TIMESTAMP_FIELDS_LEN
+ OCTO_LAYER1TO4_LEN
+ actual_octets
;
2209 record
->rec_header
.packet_header
.caplen
= OCTO_TIMESTAMP_FIELDS_LEN
+ OCTO_LAYER1TO4_LEN
+ actual_octets
;
2211 if (record
->rec_header
.packet_header
.caplen
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
2213 * Probably a corrupt capture file; return an error,
2214 * so that our caller doesn't blow up trying to allocate
2215 * space for an immensely-large packet.
2217 *err_info
= ws_strdup_printf("vwr: File has %u-byte packet, bigger than maximum of %u",
2218 record
->rec_header
.packet_header
.caplen
, WTAP_MAX_PACKET_SIZE_STANDARD
);
2219 *err
= WTAP_ERR_BAD_FILE
;
2223 record
->ts
.secs
= (time_t)s_sec
;
2224 record
->ts
.nsecs
= (int)(s_usec
* 1000);
2226 record
->rec_type
= REC_TYPE_PACKET
;
2227 record
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
2228 record
->presence_flags
= WTAP_HAS_TS
;
2230 ws_buffer_assure_space(&record
->data
, record
->rec_header
.packet_header
.caplen
);
2231 data_ptr
= ws_buffer_start_ptr(&record
->data
);
2235 * Generate and copy out the common metadata headers,
2236 * set the port type to port_type (XXX).
2238 * All values are copied out in little-endian byte order.
2240 /*** msdu_length = msdu_length + 16; ***/
2242 /* 1st octet of record for port_type and other crud */
2243 phtole8(&data_ptr
[bytes_written
], port_type
);
2247 phtole8(&data_ptr
[bytes_written
], ver_fpga
); /* 2nd octet of record for FPGA version*/
2250 phtoles(&data_ptr
[bytes_written
], OCTO_TIMESTAMP_FIELDS_LEN
); /* it_len */
2253 /*** Time Collapsible header started***/
2254 if (IS_TX
== 1 && sig_ts
!= 0) {
2255 phtolel(&data_ptr
[bytes_written
], latency
);
2257 phtolel(&data_ptr
[bytes_written
], 0);
2260 phtolel(&data_ptr
[bytes_written
], sig_ts
); /* 32 LSBs of signature timestamp (nsec) */
2262 phtolell(&data_ptr
[bytes_written
], start_time
); /* record start & end times of frame */
2264 phtolell(&data_ptr
[bytes_written
], end_time
);
2266 phtolel(&data_ptr
[bytes_written
], d_time
);
2268 /*** Time Collapsible header ends ***/
2271 /*** RF Collapsible header starts***/
2272 if (IS_TX
== 3 || IS_TX
== 4) {
2273 phtole8(&data_ptr
[bytes_written
], rf_id
);
2275 data_ptr
[bytes_written
] = 0;
2277 data_ptr
[bytes_written
] = 0;
2279 data_ptr
[bytes_written
] = 0;
2282 /*** NOISE for all 4 Ports ***/
2283 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2285 if (pntoh16(&rf_ptr
[RF_PORT_1_NOISE_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2286 phtoles(&data_ptr
[bytes_written
], 0);
2289 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_NOISE_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2291 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_NOISE_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2296 /*** SNR for all 4 Ports ***/
2297 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2299 if (pntoh16(&rf_ptr
[RF_PORT_1_SNR_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2300 phtoles(&data_ptr
[bytes_written
], 0);
2303 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_SNR_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2305 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_SNR_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2310 /*** PFE for all 4 Ports ***/
2311 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2313 if (pntoh16(&rf_ptr
[RF_PORT_1_PFE_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2314 phtoles(&data_ptr
[bytes_written
], 0);
2317 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_PFE_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2319 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_PFE_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2324 /*** EVM SIG Data for all 4 Ports ***/
2325 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2327 if (pntoh16(&rf_ptr
[RF_PORT_1_EVM_SD_SIG_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2328 phtoles(&data_ptr
[bytes_written
], 0);
2331 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SD_SIG_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2333 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SD_SIG_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2338 /*** EVM SIG PILOT for all 4 Ports ***/
2339 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2341 if (pntoh16(&rf_ptr
[RF_PORT_1_EVM_SP_SIG_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2342 phtoles(&data_ptr
[bytes_written
], 0);
2345 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SP_SIG_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2347 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SP_SIG_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2352 /*** EVM Data Data for all 4 Ports ***/
2353 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2355 if (pntoh16(&rf_ptr
[RF_PORT_1_EVM_SD_DATA_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2356 phtoles(&data_ptr
[bytes_written
], 0);
2359 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SD_DATA_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2361 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SD_DATA_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2366 /*** EVM Data PILOT for all 4 Ports ***/
2367 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2369 if (pntoh16(&rf_ptr
[RF_PORT_1_EVM_SP_DATA_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2370 phtoles(&data_ptr
[bytes_written
], 0);
2373 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SP_DATA_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2375 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_EVM_SP_DATA_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2380 /*** EVM WORST SYMBOL for all 4 Ports ***/
2381 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2383 if (pntoh16(&rf_ptr
[RF_PORT_1_DSYMBOL_IDX_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2384 phtoles(&data_ptr
[bytes_written
], 0);
2387 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_DSYMBOL_IDX_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2389 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_DSYMBOL_IDX_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2394 /*** CONTEXT_P for all 4 Ports ***/
2395 for (i
= 0; i
< RF_NUMBER_OF_PORTS
; i
++)
2397 if (pntoh16(&rf_ptr
[RF_PORT_1_CONTEXT_OFF
+i
*RF_INTER_PORT_GAP_OFF
]) == 0) {
2398 phtoles(&data_ptr
[bytes_written
], 0);
2401 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_CONTEXT_OFF
+i
*RF_INTER_PORT_GAP_OFF
];
2403 data_ptr
[bytes_written
] = rf_ptr
[RF_PORT_1_CONTEXT_OFF
+1+i
*RF_INTER_PORT_GAP_OFF
];
2408 /*** FOR rest 24 RF data bytes are commented for future use ***/
2410 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2412 if (pntoh16(&rf_ptr[20+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2413 phtoles(&data_ptr[bytes_written], 0);
2416 data_ptr[bytes_written] = rf_ptr[20+i*RF_INTER_PORT_GAP_OFF];
2418 data_ptr[bytes_written] = rf_ptr[21+i*RF_INTER_PORT_GAP_OFF];
2422 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2424 if (pntoh16(&rf_ptr[24+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2425 phtoles(&data_ptr[bytes_written], 0);
2428 data_ptr[bytes_written] = rf_ptr[24+i*RF_INTER_PORT_GAP_OFF];
2430 data_ptr[bytes_written] = rf_ptr[25+i*RF_INTER_PORT_GAP_OFF];
2434 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2436 if (pntoh16(&rf_ptr[26+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2437 phtoles(&data_ptr[bytes_written], 0);
2440 data_ptr[bytes_written] = rf_ptr[26+i*RF_INTER_PORT_GAP_OFF];
2442 data_ptr[bytes_written] = rf_ptr[27+i*RF_INTER_PORT_GAP_OFF];
2448 /*** RF Collapsible header ends***/
2452 * Generate and copy out the WLAN metadata headers.
2454 * All values are copied out in little-endian byte order.
2456 phtoles(&data_ptr
[bytes_written
], OCTO_LAYER1TO4_LEN
);
2459 /*** Layer-1 Collapsible header started***/
2460 data_ptr
[bytes_written
] = l1p_1
;
2463 data_ptr
[bytes_written
] = (nss
<< 4) | IS_TX
;
2466 phtoles(&data_ptr
[bytes_written
], phyRate
); /* To dosplay Data rate based on the PLCP type & MCS*/
2469 data_ptr
[bytes_written
] = l1p_2
;
2472 data_ptr
[bytes_written
] = rssi
[0];
2474 data_ptr
[bytes_written
] = rssi
[1];
2476 data_ptr
[bytes_written
] = rssi
[2];
2478 data_ptr
[bytes_written
] = rssi
[3];
2481 /* padding may not be required for S3_W*/
2483 data_ptr
[bytes_written
] = s_start_ptr
[2]; /*** For Signal Bandwidth Mask ***/
2485 data_ptr
[bytes_written
] = s_start_ptr
[3]; /*** For Antenna Port Energy Detect and MU_MASK ***/
2488 if (plcp_hdr_flag
== 1 && (IS_TX
== 0 || IS_TX
== 4)) {
2489 data_ptr
[bytes_written
] = L1InfoC
; /*** For Other plcp type = VHT ***/
2491 data_ptr
[bytes_written
] = 0; /*** For Other plcp type, this offset is set to 0***/
2495 phtoles(&data_ptr
[bytes_written
], msdu_length
);
2497 /*** Layer-1 Collapsible header Ends ***/
2499 /*** PLCP Collapsible header Starts ***/
2500 memcpy(&data_ptr
[bytes_written
], &rec
[stats_offset
+16], 16);
2501 bytes_written
+= 16;
2502 /*** PLCP Collapsible header Ends ***/
2504 /*** Layer 2-4 Collapsible header Starts ***/
2506 phtolel(&data_ptr
[bytes_written
], pntoh32(&s_start_ptr
[12])); /*** This 4 bytes includes BM,BV,CV,BSSID and ClientID ***/
2508 phtoles(&data_ptr
[bytes_written
], pntoh16(&s_trail_ptr
[20])); /*** 2 bytes includes FV,QT,HT,L4V,TID and WLAN type ***/
2510 data_ptr
[bytes_written
] = flow_seq
;
2512 phtole24(&data_ptr
[bytes_written
], flow_id
);
2514 phtoles(&data_ptr
[bytes_written
], pntoh16(&s_trail_ptr
[28])); /*** 2 bytes for Layer 4 ID ***/
2516 phtolel(&data_ptr
[bytes_written
], pntoh32(&s_trail_ptr
[24])); /*** 4 bytes for Payload Decode ***/
2519 /*** In case of RX, Info has 3 bytes of data, whereas for TX, 2 bytes ***/
2520 if (IS_TX
== 0 || IS_TX
== 4) {
2521 phtoles(&data_ptr
[bytes_written
], info
);
2523 data_ptr
[bytes_written
] = info_2nd
;
2527 phtoles(&data_ptr
[bytes_written
], info
);
2529 data_ptr
[bytes_written
] = 0;
2533 phtolel(&data_ptr
[bytes_written
], errors
);
2535 /*** Layer 2-4 Collapsible header Ends ***/
2537 /* Finally, copy the whole MAC frame to the packet buffer as-is.
2538 * This does not include the stats header or the PLCP.
2539 * This also does not include the last 4 bytes, as those don't
2540 * contain an FCS, they just contain junk.
2542 memcpy(&data_ptr
[bytes_written
], &rec
[stats_offset
+(vwr
->MPDU_OFF
)], actual_octets
);
2548 /* read an Ethernet packet */
2549 /* Copy the actual packet data from the capture file into the target data block. */
2550 /* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
2552 static bool vwr_read_rec_data_ethernet(vwr_t
*vwr
, wtap_rec
*record
,
2553 const uint8_t *rec
, int rec_size
,
2554 int IS_TX
, int *err
,
2558 int bytes_written
= 0; /* bytes output to buf so far */
2559 const uint8_t *s_ptr
, *m_ptr
; /* stats and MPDU pointers */
2560 uint16_t msdu_length
, actual_octets
; /* octets in frame */
2561 unsigned flow_seq
; /* seqnum */
2562 uint64_t s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
2564 uint32_t latency
= 0;
2565 uint64_t start_time
, s_sec
= LL_ZERO
, s_usec
= LL_ZERO
; /* start time, sec + usec */
2566 uint64_t end_time
; /* end time */
2568 uint16_t info
, validityBits
; /* INFO/ERRORS fields in stats */
2570 uint16_t vc_id
; /* VC ID, total (incl of aggregates) */
2571 uint32_t flow_id
, d_time
; /* packet duration */
2572 int f_flow
; /* flags: flow valid */
2573 uint32_t frame_type
; /* frame type field */
2574 int mac_len
, sig_off
, pay_off
; /* MAC header len, signature offset */
2575 /* XXX - the code here fetched tsid, but never used it! */
2576 uint64_t sig_ts
/*, tsid*/; /* 32 LSBs of timestamp in signature */
2577 uint64_t delta_b
; /* Used for calculating latency */
2578 uint16_t vw_flags
; /* VeriWave-specific packet flags */
2580 if ((unsigned)rec_size
< vwr
->STATS_LEN
) {
2581 *err_info
= ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)", rec_size
, vwr
->STATS_LEN
);
2582 *err
= WTAP_ERR_BAD_FILE
;
2586 /* Calculate the start of the statistics block in the buffer. */
2587 /* Also get a bunch of fields from the stats block. */
2588 m_ptr
= &(rec
[0]); /* point to the data block */
2589 s_ptr
= &(rec
[rec_size
- vwr
->STATS_LEN
]); /* point to the stats block */
2591 msdu_length
= pntoh16(&s_ptr
[vwr
->OCTET_OFF
]);
2592 actual_octets
= msdu_length
;
2595 * Sanity check the octets field to determine if it's greater than
2596 * the packet data available in the record - i.e., the record size
2597 * minus the length of the statistics block.
2599 * Report an error if it is.
2601 if (actual_octets
> rec_size
- vwr
->STATS_LEN
) {
2602 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
2604 *err
= WTAP_ERR_BAD_FILE
;
2608 vc_id
= pntoh16(&s_ptr
[vwr
->VCID_OFF
]) & vwr
->VCID_MASK
;
2609 flow_seq
= s_ptr
[vwr
->FLOWSEQ_OFF
];
2610 frame_type
= pntoh32(&s_ptr
[vwr
->FRAME_TYPE_OFF
]);
2612 if (vwr
->FPGA_VERSION
== vVW510024_E_FPGA
) {
2613 validityBits
= pntoh16(&s_ptr
[vwr
->VALID_OFF
]);
2614 f_flow
= validityBits
& vwr
->FLOW_VALID
;
2616 mac_len
= (validityBits
& vwr
->IS_VLAN
) ? 16 : 14; /* MAC hdr length based on VLAN tag */
2619 errors
= pntoh16(&s_ptr
[vwr
->ERRORS_OFF
]);
2622 f_flow
= s_ptr
[vwr
->VALID_OFF
] & vwr
->FLOW_VALID
;
2623 mac_len
= (frame_type
& vwr
->IS_VLAN
) ? 16 : 14; /* MAC hdr length based on VLAN tag */
2625 /* for older fpga errors is only represented by 16 bits) */
2626 errors
= pntoh16(&s_ptr
[vwr
->ERRORS_OFF
]);
2629 info
= pntoh16(&s_ptr
[vwr
->INFO_OFF
]);
2631 flow_id
= pntoh24(&s_ptr
[vwr
->FLOWID_OFF
]);
2634 /* For tx latency is duration, for rx latency is timestamp. */
2635 /* Get 64-bit latency value. */
2636 tsid
= pcorey48tohll(&s_ptr
[vwr
->LATVAL_OFF
]);
2639 l4id
= pntoh16(&s_ptr
[vwr
->L4ID_OFF
]);
2642 * The MSDU length includes the FCS.
2644 * The packet data does *not* include the FCS - it's just 4 bytes
2645 * of junk - so we have to remove it.
2647 * We'll be stripping off that junk, so make sure we have at least
2648 * 4 octets worth of packet data.
2650 * There seems to be a special case of a length of 0.
2652 if (actual_octets
< 4) {
2653 if (actual_octets
!= 0) {
2654 *err_info
= ws_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
2656 *err
= WTAP_ERR_BAD_FILE
;
2663 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
2664 /* 64-bit times are "Corey-endian" */
2665 s_time
= pcoreytohll(&s_ptr
[vwr
->STARTT_OFF
]);
2666 e_time
= pcoreytohll(&s_ptr
[vwr
->ENDT_OFF
]);
2668 /* find the packet duration (difference between start and end times) */
2669 d_time
= (uint32_t)((e_time
- s_time
)); /* find diff, leaving in nsec for Ethernet */
2671 /* also convert the packet start time to seconds and microseconds */
2672 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
2673 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
2674 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
2676 /* also convert the packet end time to seconds and microseconds */
2677 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
2679 if (frame_type
& vwr
->IS_TCP
) /* signature offset for TCP frame */
2681 pay_off
= mac_len
+ 40;
2683 else if (frame_type
& vwr
->IS_UDP
) /* signature offset for UDP frame */
2685 pay_off
= mac_len
+ 28;
2687 else if (frame_type
& vwr
->IS_ICMP
) /* signature offset for ICMP frame */
2689 pay_off
= mac_len
+ 24;
2691 else if (frame_type
& vwr
->IS_IGMP
) /* signature offset for IGMPv2 frame */
2693 pay_off
= mac_len
+ 28;
2695 else /* signature offset for raw IP frame */
2697 pay_off
= mac_len
+ 20;
2700 sig_off
= find_signature(m_ptr
, rec_size
, pay_off
, flow_id
, flow_seq
);
2701 if ((m_ptr
[sig_off
] == 0xdd) && (f_flow
!= 0))
2702 sig_ts
= get_signature_ts(m_ptr
, sig_off
, msdu_length
);
2706 /* Set latency based on rx/tx and signature timestamp */
2708 if (sig_ts
< s_time
) {
2709 latency
= (uint32_t)(s_time
- sig_ts
);
2711 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
2712 /* we look for a large difference between l_time and s_time. */
2713 delta_b
= sig_ts
- s_time
;
2714 if (delta_b
> 0x10000000) {
2717 latency
= (uint32_t)delta_b
;
2722 * Fill up the per-packet header.
2724 * We include the length of the metadata headers in the packet lengths.
2726 * The maximum value of actual_octets is 65535, which, even after
2727 * adding the lengths of the metadata headers, is less than
2728 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
2730 record
->rec_header
.packet_header
.len
= STATS_COMMON_FIELDS_LEN
+ EXT_ETHERNET_FIELDS_LEN
+ actual_octets
;
2731 record
->rec_header
.packet_header
.caplen
= STATS_COMMON_FIELDS_LEN
+ EXT_ETHERNET_FIELDS_LEN
+ actual_octets
;
2733 record
->ts
.secs
= (time_t)s_sec
;
2734 record
->ts
.nsecs
= (int)(s_usec
* 1000);
2736 record
->rec_type
= REC_TYPE_PACKET
;
2737 record
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
2738 record
->presence_flags
= WTAP_HAS_TS
;
2740 /*etap_hdr.vw_ip_length = (uint16_t)ip_len;*/
2742 ws_buffer_assure_space(&record
->data
, record
->rec_header
.packet_header
.caplen
);
2743 data_ptr
= ws_buffer_start_ptr(&record
->data
);
2746 * Generate and copy out the common metadata headers,
2747 * set the port type to 1 (Ethernet).
2749 * All values are copied out in little-endian byte order.
2751 /* 1st octet of record for port_type and command (command is 0, hence RX) */
2752 phtole8(&data_ptr
[bytes_written
], ETHERNET_PORT
);
2754 /* 2nd octet of record for fpga version (Ethernet, hence non-OCTO) */
2755 phtole8(&data_ptr
[bytes_written
], 0);
2758 phtoles(&data_ptr
[bytes_written
], STATS_COMMON_FIELDS_LEN
);
2760 phtoles(&data_ptr
[bytes_written
], msdu_length
);
2762 phtolel(&data_ptr
[bytes_written
], flow_id
);
2764 phtoles(&data_ptr
[bytes_written
], vc_id
);
2766 phtoles(&data_ptr
[bytes_written
], flow_seq
);
2768 if (!IS_TX
&& (sig_ts
!= 0)) {
2769 phtolel(&data_ptr
[bytes_written
], latency
);
2771 phtolel(&data_ptr
[bytes_written
], 0);
2774 phtolel(&data_ptr
[bytes_written
], sig_ts
);
2776 phtolell(&data_ptr
[bytes_written
], start_time
) /* record start & end times of frame */
2778 phtolell(&data_ptr
[bytes_written
], end_time
);
2780 phtolel(&data_ptr
[bytes_written
], d_time
);
2784 * Generate and copy out the Ethernet metadata headers.
2786 * All values are copied out in little-endian byte order.
2788 phtoles(&data_ptr
[bytes_written
], EXT_ETHERNET_FIELDS_LEN
);
2792 vw_flags
|= VW_FLAGS_TXF
;
2793 if (errors
& vwr
->FCS_ERROR
)
2794 vw_flags
|= VW_FLAGS_FCSERR
;
2795 phtoles(&data_ptr
[bytes_written
], vw_flags
);
2797 phtoles(&data_ptr
[bytes_written
], info
);
2799 phtolel(&data_ptr
[bytes_written
], errors
);
2801 phtolel(&data_ptr
[bytes_written
], l4id
);
2805 phtolel(&data_ptr
[bytes_written
], 0);
2809 * Finally, copy the whole MAC frame to the packet buffer as-is.
2810 * This also does not include the last 4 bytes, as those don't
2811 * contain an FCS, they just contain junk.
2813 memcpy(&data_ptr
[bytes_written
], m_ptr
, actual_octets
);
2818 /*--------------------------------------------------------------------------------------*/
2819 /* utility to split up and decode a 16-byte message record */
2821 static int decode_msg(vwr_t
*vwr
, uint8_t *rec
, int *v_type
, int *IS_TX
, int *log_mode
)
2823 uint8_t cmd
,fpga_log_mode
; /* components of message */
2825 int v_size
; /* size of var-len message */
2827 /* break up the message record into its pieces */
2829 fpga_log_mode
= rec
[1];
2830 fpga_log_mode
= ((fpga_log_mode
& 0x30) >> 4);
2832 wd2
= pntoh32(&rec
[8]);
2833 wd3
= pntoh32(&rec
[12]);
2836 *log_mode
= fpga_log_mode
; /* Log mode = 3, when MPDU data is reduced */
2838 /* now decode based on the command byte */
2844 v_size
= (int)(wd2
& 0xffff);
2852 v_size
= (int)(wd2
& 0xffff);
2861 v_size = (int)(wd2 & 0xffff);
2866 case COMMAND_RF
: /* For RF Modified only */
2870 v_size
= (int)(wd2
& 0xffff);
2874 case COMMAND_RFRX
: /* For RF_RX Modified only */
2878 v_size
= (int)(wd2
& 0xffff);
2888 v_size
= (int)(wd2
& 0xffff);
2896 v_size
= (int)(wd3
& 0xffff);
2905 *v_type
= VT_UNKNOWN
;
2913 /*---------------------------------------------------------------------------------------*/
2914 /* Utilities to extract and decode the PHY bit rate from 802.11 PLCP headers (OFDM/CCK). */
2915 /* They are passed a pointer to 4 or 6 consecutive bytes of PLCP header. */
2916 /* The integer returned by the get_xxx_rate() functions is in units of 0.5 Mb/s. */
2917 /* The string returned by the decode_xxx_rate() functions is 3 characters wide. */
2919 static uint8_t get_ofdm_rate(const uint8_t *plcp
)
2921 /* extract the RATE field (LS nibble of first byte) then convert it to the MCS index used by the L1p fields */
2922 switch (plcp
[0] & 0x0f) {
2923 case 0x0b: return 4;
2924 case 0x0f: return 5;
2925 case 0x0a: return 6;
2926 case 0x0e: return 7;
2927 case 0x09: return 8;
2928 case 0x0d: return 9;
2929 case 0x08: return 10;
2930 case 0x0c: return 11;
2935 static uint8_t get_cck_rate(const uint8_t *plcp
)
2937 /* extract rate from the SIGNAL field then convert it to the MCS index used by the L1p fields */
2939 case 0x0a: return 0;
2940 case 0x14: return 1;
2941 case 0x37: return 2;
2942 case 0x6e: return 3;
2947 /*--------------------------------------------------------------------------------------*/
2948 /* utility to set up offsets and bitmasks for decoding the stats blocks */
2950 static void setup_defaults(vwr_t
*vwr
, uint16_t fpga
)
2955 vwr
->STATS_LEN
= vVW510021_W_STATS_TRAILER_LEN
;
2957 vwr
->VALID_OFF
= vVW510021_W_VALID_OFF
;
2958 vwr
->MTYPE_OFF
= vVW510021_W_MTYPE_OFF
;
2959 vwr
->VCID_OFF
= vVW510021_W_VCID_OFF
;
2960 vwr
->FLOWSEQ_OFF
= vVW510021_W_FLOWSEQ_OFF
;
2961 vwr
->FLOWID_OFF
= vVW510021_W_FLOWID_OFF
;
2963 /*vwr->OCTET_OFF = v22_W_OCTET_OFF;*/
2965 vwr
->ERRORS_OFF
= vVW510021_W_ERRORS_OFF
;
2966 vwr
->PATN_OFF
= vVW510021_W_MATCH_OFF
;
2967 vwr
->RSSI_OFF
= vVW510021_W_RSSI_TXPOWER_OFF
;
2968 vwr
->STARTT_OFF
= vVW510021_W_STARTT_OFF
;
2969 vwr
->ENDT_OFF
= vVW510021_W_ENDT_OFF
;
2970 vwr
->LATVAL_OFF
= vVW510021_W_LATVAL_OFF
;
2971 vwr
->INFO_OFF
= vVW510021_W_INFO_OFF
;
2972 vwr
->FPGA_VERSION_OFF
= S2_W_FPGA_VERSION_OFF
;
2973 vwr
->HEADER_VERSION_OFF
= vVW510021_W_HEADER_VERSION_OFF
;
2974 vwr
->OCTET_OFF
= vVW510021_W_MSDU_LENGTH_OFF
;
2975 vwr
->L1P_1_OFF
= vVW510021_W_L1P_1_OFF
;
2976 vwr
->L1P_2_OFF
= vVW510021_W_L1P_2_OFF
;
2977 vwr
->L4ID_OFF
= vVW510021_W_L4ID_OFF
;
2978 vwr
->IPLEN_OFF
= vVW510021_W_IPLEN_OFF
;
2979 vwr
->PLCP_LENGTH_OFF
= vVW510021_W_PLCP_LENGTH_OFF
;
2981 vwr
->MT_MASK
= vVW510021_W_SEL_MASK
;
2982 vwr
->MCS_INDEX_MASK
= vVW510021_W_MCS_MASK
;
2983 vwr
->VCID_MASK
= 0xffff;
2984 vwr
->FLOW_VALID
= vVW510021_W_FLOW_VALID
;
2985 vwr
->STATS_START_OFF
= vVW510021_W_HEADER_LEN
;
2986 vwr
->FCS_ERROR
= vVW510021_W_FCS_ERROR
;
2987 vwr
->CRYPTO_ERR
= v22_W_CRYPTO_ERR
;
2988 vwr
->RETRY_ERR
= v22_W_RETRY_ERR
;
2990 /*vwr->STATS_START_OFF = 0;*/
2992 vwr
->RXTX_OFF
= vVW510021_W_RXTX_OFF
;
2994 vwr
->MT_10_HALF
= 0;
2995 vwr
->MT_10_FULL
= 0;
2996 vwr
->MT_100_HALF
= 0;
2997 vwr
->MT_100_FULL
= 0;
2998 vwr
->MT_1G_HALF
= 0;
2999 vwr
->MT_1G_FULL
= 0;
3000 vwr
->MT_CCKL
= v22_W_MT_CCKL
;
3001 vwr
->MT_CCKS
= v22_W_MT_CCKS
;
3002 /*vwr->MT_OFDM = vVW510021_W_MT_OFDM;*/
3004 vwr
->WEPTYPE
= vVW510021_W_WEPTYPE
;
3005 vwr
->TKIPTYPE
= vVW510021_W_TKIPTYPE
;
3006 vwr
->CCMPTYPE
= vVW510021_W_CCMPTYPE
;
3008 vwr
->FRAME_TYPE_OFF
= vVW510021_W_FRAME_TYPE_OFF
;
3009 vwr
->IS_TCP
= vVW510021_W_IS_TCP
;
3010 vwr
->IS_UDP
= vVW510021_W_IS_UDP
;
3011 vwr
->IS_ICMP
= vVW510021_W_IS_ICMP
;
3012 vwr
->IS_IGMP
= vVW510021_W_IS_IGMP
;
3013 vwr
->IS_QOS
= vVW510021_W_QOS_VALID
;
3016 * vVW510021_W_STATS_HEADER_LEN = 8 is:
3018 * 2 bytes of l1p_1/l1p_2;
3020 * 2 bytes of MSDU length + other bits
3024 * The 12 is for 11 bytes of PLCP and 1 byte of pad
3027 vwr
->MPDU_OFF
= vVW510021_W_STATS_HEADER_LEN
+ 12;
3032 vwr
->STATS_LEN
= vVW510021_W_STATS_TRAILER_LEN
;
3033 vwr
->PLCP_LENGTH_OFF
= 16;
3038 * 2 bytes of l1p_1/l1p_2;
3039 * 1 byte of signal bandwidth mask;
3040 * 1 byte of antenna port energy;
3041 * 4 bytes of per-antenna RSSI;
3042 * 1 byte of L1InfoC;
3043 * 3 bytes of MSDU length;
3044 * 4 bytes of something;
3047 vwr
->MPDU_OFF
= 16 + 16;
3051 case vVW510012_E_FPGA
:
3052 vwr
->STATS_LEN
= v22_E_STATS_LEN
;
3054 vwr
->VALID_OFF
= v22_E_VALID_OFF
;
3055 vwr
->MTYPE_OFF
= v22_E_MTYPE_OFF
;
3056 vwr
->VCID_OFF
= v22_E_VCID_OFF
;
3057 vwr
->FLOWSEQ_OFF
= v22_E_FLOWSEQ_OFF
;
3058 vwr
->FLOWID_OFF
= v22_E_FLOWID_OFF
;
3059 vwr
->OCTET_OFF
= v22_E_OCTET_OFF
;
3060 vwr
->ERRORS_OFF
= v22_E_ERRORS_OFF
;
3061 vwr
->PATN_OFF
= v22_E_PATN_OFF
;
3062 vwr
->RSSI_OFF
= v22_E_RSSI_OFF
;
3063 vwr
->STARTT_OFF
= v22_E_STARTT_OFF
;
3064 vwr
->ENDT_OFF
= v22_E_ENDT_OFF
;
3065 vwr
->LATVAL_OFF
= v22_E_LATVAL_OFF
;
3066 vwr
->INFO_OFF
= v22_E_INFO_OFF
;
3067 vwr
->L4ID_OFF
= v22_E_L4ID_OFF
;
3069 vwr
->IS_RX
= v22_E_IS_RX
;
3070 vwr
->MT_MASK
= v22_E_MT_MASK
;
3071 vwr
->VCID_MASK
= v22_E_VCID_MASK
;
3072 vwr
->FLOW_VALID
= v22_E_FLOW_VALID
;
3073 vwr
->FCS_ERROR
= v22_E_FCS_ERROR
;
3075 vwr
->RX_DECRYPTS
= v22_E_RX_DECRYPTS
;
3076 vwr
->TX_DECRYPTS
= v22_E_TX_DECRYPTS
;
3077 vwr
->FC_PROT_BIT
= v22_E_FC_PROT_BIT
;
3079 vwr
->MT_10_HALF
= v22_E_MT_10_HALF
;
3080 vwr
->MT_10_FULL
= v22_E_MT_10_FULL
;
3081 vwr
->MT_100_HALF
= v22_E_MT_100_HALF
;
3082 vwr
->MT_100_FULL
= v22_E_MT_100_FULL
;
3083 vwr
->MT_1G_HALF
= v22_E_MT_1G_HALF
;
3084 vwr
->MT_1G_FULL
= v22_E_MT_1G_FULL
;
3089 vwr
->FRAME_TYPE_OFF
= v22_E_FRAME_TYPE_OFF
;
3090 vwr
->IS_TCP
= v22_E_IS_TCP
;
3091 vwr
->IS_UDP
= v22_E_IS_UDP
;
3092 vwr
->IS_ICMP
= v22_E_IS_ICMP
;
3093 vwr
->IS_IGMP
= v22_E_IS_IGMP
;
3094 vwr
->IS_QOS
= v22_E_IS_QOS
;
3095 vwr
->IS_VLAN
= v22_E_IS_VLAN
;
3101 vwr
->STATS_LEN
= v22_W_STATS_LEN
;
3103 vwr
->MTYPE_OFF
= v22_W_MTYPE_OFF
;
3104 vwr
->VALID_OFF
= v22_W_VALID_OFF
;
3105 vwr
->VCID_OFF
= v22_W_VCID_OFF
;
3106 vwr
->FLOWSEQ_OFF
= v22_W_FLOWSEQ_OFF
;
3107 vwr
->FLOWID_OFF
= v22_W_FLOWID_OFF
;
3108 vwr
->OCTET_OFF
= v22_W_OCTET_OFF
;
3109 vwr
->ERRORS_OFF
= v22_W_ERRORS_OFF
;
3110 vwr
->PATN_OFF
= v22_W_PATN_OFF
;
3111 vwr
->RSSI_OFF
= v22_W_RSSI_OFF
;
3112 vwr
->STARTT_OFF
= v22_W_STARTT_OFF
;
3113 vwr
->ENDT_OFF
= v22_W_ENDT_OFF
;
3114 vwr
->LATVAL_OFF
= v22_W_LATVAL_OFF
;
3115 vwr
->INFO_OFF
= v22_W_INFO_OFF
;
3116 vwr
->L4ID_OFF
= v22_W_L4ID_OFF
;
3117 vwr
->IPLEN_OFF
= v22_W_IPLEN_OFF
;
3118 vwr
->PLCP_LENGTH_OFF
= v22_W_PLCP_LENGTH_OFF
;
3120 vwr
->FCS_ERROR
= v22_W_FCS_ERROR
;
3121 vwr
->CRYPTO_ERR
= v22_W_CRYPTO_ERR
;
3122 vwr
->PAYCHK_ERR
= v22_W_PAYCHK_ERR
;
3123 vwr
->RETRY_ERR
= v22_W_RETRY_ERR
;
3124 vwr
->IS_RX
= v22_W_IS_RX
;
3125 vwr
->MT_MASK
= v22_W_MT_MASK
;
3126 vwr
->VCID_MASK
= v22_W_VCID_MASK
;
3127 vwr
->FLOW_VALID
= v22_W_FLOW_VALID
;
3129 vwr
->RX_DECRYPTS
= v22_W_RX_DECRYPTS
;
3130 vwr
->TX_DECRYPTS
= v22_W_TX_DECRYPTS
;
3131 vwr
->FC_PROT_BIT
= v22_W_FC_PROT_BIT
;
3133 vwr
->MT_10_HALF
= 0;
3134 vwr
->MT_10_FULL
= 0;
3135 vwr
->MT_100_HALF
= 0;
3136 vwr
->MT_100_FULL
= 0;
3137 vwr
->MT_1G_HALF
= 0;
3138 vwr
->MT_1G_FULL
= 0;
3139 vwr
->MT_CCKL
= v22_W_MT_CCKL
;
3140 vwr
->MT_CCKS
= v22_W_MT_CCKS
;
3141 vwr
->MT_OFDM
= v22_W_MT_OFDM
;
3143 vwr
->WEPTYPE
= v22_W_WEPTYPE
;
3144 vwr
->TKIPTYPE
= v22_W_TKIPTYPE
;
3145 vwr
->CCMPTYPE
= v22_W_CCMPTYPE
;
3147 vwr
->FRAME_TYPE_OFF
= v22_W_FRAME_TYPE_OFF
;
3148 vwr
->IS_TCP
= v22_W_IS_TCP
;
3149 vwr
->IS_UDP
= v22_W_IS_UDP
;
3150 vwr
->IS_ICMP
= v22_W_IS_ICMP
;
3151 vwr
->IS_IGMP
= v22_W_IS_IGMP
;
3152 vwr
->IS_QOS
= v22_W_IS_QOS
;
3156 /* Ethernet frames */
3157 case vVW510024_E_FPGA
:
3158 vwr
->STATS_LEN
= vVW510024_E_STATS_LEN
;
3160 vwr
->VALID_OFF
= vVW510024_E_VALID_OFF
;
3161 vwr
->VCID_OFF
= vVW510024_E_VCID_OFF
;
3162 vwr
->FLOWSEQ_OFF
= vVW510024_E_FLOWSEQ_OFF
;
3163 vwr
->FLOWID_OFF
= vVW510024_E_FLOWID_OFF
;
3164 vwr
->OCTET_OFF
= vVW510024_E_MSDU_LENGTH_OFF
;
3165 vwr
->ERRORS_OFF
= vVW510024_E_ERRORS_OFF
;
3166 vwr
->PATN_OFF
= vVW510024_E_MATCH_OFF
;
3167 vwr
->STARTT_OFF
= vVW510024_E_STARTT_OFF
;
3168 vwr
->ENDT_OFF
= vVW510024_E_ENDT_OFF
;
3169 vwr
->LATVAL_OFF
= vVW510024_E_LATVAL_OFF
;
3170 vwr
->INFO_OFF
= vVW510024_E_INFO_OFF
;
3171 vwr
->L4ID_OFF
= vVW510024_E_L4ID_OFF
;
3172 vwr
->IPLEN_OFF
= vVW510024_E_IPLEN_OFF
;
3174 vwr
->FPGA_VERSION_OFF
= vVW510024_E_FPGA_VERSION_OFF
;
3175 vwr
->HEADER_VERSION_OFF
= vVW510024_E_HEADER_VERSION_OFF
;
3177 vwr
->VCID_MASK
= vVW510024_E_VCID_MASK
;
3178 vwr
->FLOW_VALID
= vVW510024_E_FLOW_VALID
;
3179 vwr
->FCS_ERROR
= v22_E_FCS_ERROR
;
3181 vwr
->FRAME_TYPE_OFF
= vVW510024_E_FRAME_TYPE_OFF
;
3182 vwr
->IS_TCP
= vVW510024_E_IS_TCP
;
3183 vwr
->IS_UDP
= vVW510024_E_IS_UDP
;
3184 vwr
->IS_ICMP
= vVW510024_E_IS_ICMP
;
3185 vwr
->IS_IGMP
= vVW510024_E_IS_IGMP
;
3186 vwr
->IS_QOS
= vVW510024_E_QOS_VALID
;
3187 vwr
->IS_VLAN
= vVW510024_E_IS_VLAN
;
3192 #define SIG_SCAN_RANGE 64 /* range of signature scanning region */
3194 /* Utility routine: check that signature is at specified location; scan for it if not. */
3195 /* If we can't find a signature at all, then simply return the originally supplied offset. */
3196 int find_signature(const uint8_t *m_ptr
, int rec_size
, int pay_off
, uint32_t flow_id
, uint8_t flow_seq
)
3198 int tgt
; /* temps */
3201 /* initial check is very simple: look for a '0xdd' at the target location */
3202 if (m_ptr
[pay_off
] == 0xdd) /* if magic byte is present */
3203 return pay_off
; /* got right offset, return it */
3205 /* Hmmm, signature magic byte is not where it is supposed to be; scan from start of */
3206 /* payload until maximum scan range exhausted to see if we can find it. */
3207 /* The scanning process consists of looking for a '0xdd', then checking for the correct */
3208 /* flow ID and sequence number at the appropriate offsets. */
3209 for (tgt
= pay_off
; tgt
< (rec_size
); tgt
++) {
3210 if (m_ptr
[tgt
] == 0xdd) { /* found magic byte? check fields */
3211 if ((tgt
+ 15 < rec_size
) && (m_ptr
[tgt
+ 15] == 0xe2)) {
3212 if (m_ptr
[tgt
+ 4] != flow_seq
)
3215 fid
= pletoh24(&m_ptr
[tgt
+ 1]);
3222 else if (tgt
+ SIG_FSQ_OFF
< rec_size
)
3223 { /* out which one... */
3224 if (m_ptr
[tgt
+ SIG_FSQ_OFF
] != flow_seq
) /* check sequence number */
3225 continue; /* if failed, keep scanning */
3227 fid
= pletoh24(&m_ptr
[tgt
+ SIG_FID_OFF
]); /* assemble flow ID from signature */
3228 if (fid
!= flow_id
) /* check flow ID against expected */
3229 continue; /* if failed, keep scanning */
3231 /* matched magic byte, sequence number, flow ID; found the signature */
3232 return (tgt
); /* return offset of signature */
3237 /* failed to find the signature, return the original offset as default */
3241 /* utility routine: harvest the signature time stamp from the data frame */
3242 uint64_t get_signature_ts(const uint8_t *m_ptr
,int sig_off
, int sig_max
)
3247 if (sig_off
+ 15 >= sig_max
)
3250 if (m_ptr
[sig_off
+ 15] == 0xe2)
3255 sig_ts
= pletoh32(&m_ptr
[sig_off
+ ts_offset
]);
3257 return (sig_ts
& 0xffffffff);
3261 get_legacy_rate(uint8_t rate_index
)
3263 /* Rate conversion data */
3264 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
};
3266 float bitrate
= 0.0f
;
3268 if (rate_index
< G_N_ELEMENTS(canonical_rate_legacy
))
3269 bitrate
= canonical_rate_legacy
[rate_index
];
3275 get_ht_rate(uint8_t mcs_index
, uint16_t rflags
)
3277 /* Rate conversion data */
3278 static const int canonical_ndbps_20_ht
[8] = {26, 52, 78, 104, 156, 208, 234, 260};
3279 static const int canonical_ndbps_40_ht
[8] = {54, 108, 162, 216, 324, 432, 486, 540};
3281 float symbol_tx_time
, bitrate
;
3284 if (rflags
& FLAGS_CHAN_SHORTGI
)
3285 symbol_tx_time
= 3.6f
;
3287 symbol_tx_time
= 4.0f
;
3289 if (rflags
& FLAGS_CHAN_40MHZ
)
3290 ndbps
= canonical_ndbps_40_ht
[mcs_index
- 8*(int)(mcs_index
/8)];
3292 ndbps
= canonical_ndbps_20_ht
[mcs_index
- 8*(int)(mcs_index
/8)];
3294 bitrate
= (ndbps
* (((int)(mcs_index
>> 3) + 1))) / symbol_tx_time
;
3300 get_vht_rate(uint8_t mcs_index
, uint16_t rflags
, uint8_t nss
)
3302 /* Rate conversion data */
3303 static const int canonical_ndbps_20_vht
[9] = {26, 52, 78, 104, 156, 208, 234, 260, 312};
3304 static const int canonical_ndbps_40_vht
[10] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
3305 static const int canonical_ndbps_80_vht
[10] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
3307 float symbol_tx_time
, bitrate
;
3309 if (rflags
& FLAGS_CHAN_SHORTGI
)
3310 symbol_tx_time
= 3.6f
;
3312 symbol_tx_time
= 4.0f
;
3315 * Check for the out of range mcs_index.
3316 * Should never happen, but if mcs index is greater than 9 just
3321 if (rflags
& FLAGS_CHAN_40MHZ
)
3322 bitrate
= (canonical_ndbps_40_vht
[mcs_index
] * nss
) / symbol_tx_time
;
3323 else if (rflags
& FLAGS_CHAN_80MHZ
)
3324 bitrate
= (canonical_ndbps_80_vht
[mcs_index
] * nss
) / symbol_tx_time
;
3329 /* This is a special case for 20 MHz. */
3331 bitrate
= 1040 / symbol_tx_time
;
3333 bitrate
= 2080 / symbol_tx_time
;
3338 bitrate
= (canonical_ndbps_20_vht
[mcs_index
] * nss
) / symbol_tx_time
;
3345 vwr_process_rec_data(FILE_T fh
, int rec_size
, wtap_rec
*record
, vwr_t
*vwr
,
3346 int IS_TX
, int log_mode
, int *err
, char **err_info
)
3348 uint8_t* rec
; /* local buffer (holds input record) */
3351 rec
= (uint8_t*)g_malloc(B_SIZE
);
3353 /* Read over the entire record (frame + trailer) into a local buffer. */
3354 /* If we don't get it all, then declare an error, we can't process the frame. */
3355 if (!wtap_read_bytes(fh
, rec
, rec_size
, err
, err_info
))
3361 /* now format up the frame data */
3362 switch (vwr
->FPGA_VERSION
)
3365 ret
= vwr_read_s1_W_rec(vwr
, record
, rec
, rec_size
, err
, err_info
);
3368 ret
= vwr_read_s2_W_rec(vwr
, record
, rec
, rec_size
, IS_TX
, err
, err_info
);
3371 ret
= vwr_read_s3_W_rec(vwr
, record
, rec
, rec_size
, IS_TX
, log_mode
, err
, err_info
);
3373 case vVW510012_E_FPGA
:
3374 case vVW510024_E_FPGA
:
3375 ret
= vwr_read_rec_data_ethernet(vwr
, record
, rec
, rec_size
, IS_TX
, err
, err_info
);
3379 ws_assert_not_reached();
3387 static const struct supported_block_type vwr_80211_blocks_supported
[] = {
3389 * We support packet blocks, with no comments or other options.
3391 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
3394 static const struct file_type_subtype_info vwr_80211_info
= {
3395 "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL
,
3396 false, BLOCKS_SUPPORTED(vwr_80211_blocks_supported
),
3400 static const struct supported_block_type vwr_eth_blocks_supported
[] = {
3402 * We support packet blocks, with no comments or other options.
3404 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
3407 static const struct file_type_subtype_info vwr_eth_info
= {
3408 "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL
,
3409 false, BLOCKS_SUPPORTED(vwr_eth_blocks_supported
),
3413 void register_vwr(void)
3415 vwr_80211_file_type_subtype
= wtap_register_file_type_subtype(&vwr_80211_info
);
3416 vwr_eth_file_type_subtype
= wtap_register_file_type_subtype(&vwr_eth_info
);
3419 * Register names for backwards compatibility with the
3420 * wtap_filetypes table in Lua.
3422 wtap_register_backwards_compatibility_lua_name("VWR_80211",
3423 vwr_80211_file_type_subtype
);
3424 wtap_register_backwards_compatibility_lua_name("VWR_ETH",
3425 vwr_eth_file_type_subtype
);
3429 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3434 * indent-tabs-mode: nil
3437 * vi: set shiftwidth=4 tabstop=8 expandtab:
3438 * :indentSize=4:tabSize=8:noTabs=true: