2 * Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
5 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "file_wrappers.h"
32 /* platform-specific definitions for portability */
34 /* unsigned long long constants */
35 # define NS_IN_US G_GUINT64_CONSTANT(1000) /* nanoseconds-to-microseconds */
36 # define NS_IN_SEC G_GUINT64_CONSTANT(1000000000) /* nanoseconds-to-seconds */
37 # define US_IN_SEC G_GUINT64_CONSTANT(1000000) /* microseconds-to-seconds */
38 # define LL_ZERO G_GUINT64_CONSTANT(0) /* zero in unsigned long long */
41 * Fetch a 64-bit value in "Corey-endian" form.
43 #define pcoreytohll(p) ((guint64)*((const guint8 *)(p)+4)<<56| \
44 (guint64)*((const guint8 *)(p)+5)<<48| \
45 (guint64)*((const guint8 *)(p)+6)<<40| \
46 (guint64)*((const guint8 *)(p)+7)<<32| \
47 (guint64)*((const guint8 *)(p)+0)<<24| \
48 (guint64)*((const guint8 *)(p)+1)<<16| \
49 (guint64)*((const guint8 *)(p)+2)<<8| \
50 (guint64)*((const guint8 *)(p)+3)<<0)
53 * Fetch a 48-bit value in "Corey-endian" form; it's stored as
54 * a 64-bit Corey-endian value, with the upper 16 bits ignored.
56 #define pcorey48tohll(p) ((guint64)*((const guint8 *)(p)+6)<<40| \
57 (guint64)*((const guint8 *)(p)+7)<<32| \
58 (guint64)*((const guint8 *)(p)+0)<<24| \
59 (guint64)*((const guint8 *)(p)+1)<<16| \
60 (guint64)*((const guint8 *)(p)+2)<<8| \
61 (guint64)*((const guint8 *)(p)+3)<<0)
63 /* .vwr log file defines */
64 #define B_SIZE 32768 /* max var len message = 32 kB */
65 #define VT_FRAME 0 /* varlen msg is a frame */
66 #define VT_CPMSG 1 /* varlen msg is a CP<->PP msg */
67 #define MAX_TRACKED_CLIENTS 1024 /* track 1024 clients */
68 #define MAX_TRACKED_FLOWS 65536 /* and 64K flows */
71 * The file consists of a sequence of records.
72 * A record begins with a 16-byte header, the first 8 bytes of which
73 * begin with a byte containing a command plus transmit-receive flags.
75 * Following that are two big-endian 32-bit quantities; for some records
76 * one or the other of them is the length of the rest of the record.
77 * Other records contain only the header.
79 #define VW_RECORD_HEADER_LENGTH 16
81 /* Command byte values */
82 #define COMMAND_RX 0x21
83 #define COMMAND_TX 0x31
85 /* the metadata headers */
87 /* Size of the IxVeriwave common header */
88 #define STATS_COMMON_FIELDS_LEN (2+2+2+4+2+2+4+4+8+8+4)
90 /* For VeriWave WLAN and Ethernet metadata headers vw_flags field */
91 #define VW_FLAGS_TXF 0x01 /* frame was transmitted */
92 #define VW_FLAGS_FCSERR 0x02 /* FCS error detected */
94 /* For VeriWave WLAN metadata header vw_flags field */
95 #define VW_FLAGS_RETRERR 0x04 /* excess retry error detected */
96 #define VW_FLAGS_DCRERR 0x10 /* decrypt error detected (WLAN) */
97 #define VW_FLAGS_ENCMSK 0x60 /* encryption type mask */
98 /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
99 #define VW_FLAGS_IS_WEP 0x20 /* WEP */
100 #define VW_FLAGS_IS_TKIP 0x40 /* TKIP */
101 #define VW_FLAGS_IS_CCMP 0x60 /* CCMP */
103 /* Veriwave WLAN metadata header */
105 /* Channel flags, for chanflags field */
106 #define CHAN_CCK 0x0020 /* CCK channel */
107 #define CHAN_OFDM 0x0040 /* OFDM channel */
109 /* Flags, for flags field */
110 #define FLAGS_SHORTPRE 0x0002 /* sent/received with short preamble */
111 #define FLAGS_WEP 0x0004 /* sent/received with WEP encryption */
112 #define FLAGS_FCS 0x0010 /* frame includes FCS */
113 #define FLAGS_CHAN_HT 0x0040 /* In HT mode */
114 #define FLAGS_CHAN_VHT 0x0080 /* VHT Mode */
115 #define FLAGS_CHAN_SHORTGI 0x0100 /* Short guard interval */
116 #define FLAGS_CHAN_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
117 #define FLAGS_CHAN_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
118 #define FLAGS_CHAN_160MHZ 0x0800 /* 160 Mhz channel bandwidth */
120 /* Size of the VeriWave WLAN metadata header */
121 #define EXT_WLAN_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
123 /* Size of the VeriWave Ethernet metadata header */
124 #define EXT_ETHERNET_FIELDS_LEN (2+2+2+4+4+4)
126 /* FPGA-generated frame buffer STATS block offsets and definitions */
128 /* definitions for v2.2 frames, Ethernet format */
129 #define v22_E_STATS_LEN 44 /* length of stats block trailer */
130 #define v22_E_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
131 #define v22_E_MTYPE_OFF 1 /* offset of modulation type */
132 #define v22_E_VCID_OFF 2 /* offset of VC ID */
133 #define v22_E_FLOWSEQ_OFF 4 /* offset of signature sequence number */
134 #define v22_E_FLOWID_OFF 5 /* offset of flow ID */
135 #define v22_E_OCTET_OFF 8 /* offset of octets */
136 #define v22_E_ERRORS_OFF 10 /* offset of error vector */
137 #define v22_E_PATN_OFF 12 /* offset of pattern match vector */
138 #define v22_E_L4ID_OFF 12
139 #define v22_E_IPLEN_OFF 14
140 #define v22_E_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
141 #define v22_E_RSSI_OFF 21 /* RSSI (NOTE: invalid for Ethernet) */
142 #define v22_E_STARTT_OFF 20 /* offset of start time, 64 bits */
143 #define v22_E_ENDT_OFF 28 /* offset of end time, 64 bits */
144 #define v22_E_LATVAL_OFF 36 /* offset of latency, 32 bits */
145 #define v22_E_INFO_OFF 40 /* NO INFO FIELD IN ETHERNET STATS! */
146 #define v22_E_DIFFERENTIATOR_OFF 0 /* offset to determine whether */
147 /* eth/802.11, 8 bits */
149 #define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
150 #define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
151 #define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
152 #define v22_E_MT_100_FULL 3 /* 100 Mb/s full-duplex */
153 #define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
154 #define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
157 #define v22_E_FCS_ERROR 0x0002 /* FCS error flag in error vector */
158 #define v22_E_CRYPTO_ERR 0x1f00 /* RX decrypt error flags (UNUSED) */
159 #define v22_E_SIG_ERR 0x0004 /* signature magic byte mismatch */
160 #define v22_E_PAYCHK_ERR 0x0008 /* payload checksum failure */
161 #define v22_E_RETRY_ERR 0x0400 /* excessive retries on TX fail (UNUSED)*/
163 /* Masks and defines */
164 #define v22_E_IS_RX 0x08 /* TX/RX bit in STATS block */
165 #define v22_E_MT_MASK 0x07 /* modulation type mask (UNUSED) */
167 #define v22_E_VCID_MASK 0x03ff /* VC ID is only 10 bits */
169 #define v22_E_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
171 #define v22_E_DIFFERENTIATOR_MASK 0X3F /* mask to differentiate ethernet from */
173 /* Bits in FRAME_TYPE field */
174 #define v22_E_IS_TCP 0x00000040 /* TCP */
175 #define v22_E_IS_UDP 0x00000010 /* UDP */
176 #define v22_E_IS_ICMP 0x00000020 /* ICMP */
177 #define v22_E_IS_IGMP 0x00000080 /* IGMP */
179 #define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
180 #define v22_E_IS_VLAN 0x00200000
183 #define v22_E_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted (UNUSED) */
184 #define v22_E_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted (UNUSED) */
186 #define v22_E_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
188 #define v22_E_IS_ETHERNET 0x00700000 /* bits set in frame type if ethernet */
189 #define v22_E_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
191 /* definitions for v2.2 frames, WLAN format for VW510006 FPGA*/
192 #define v22_W_STATS_LEN 64 /* length of stats block trailer */
193 #define v22_W_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
194 #define v22_W_MTYPE_OFF 1 /* offset of modulation type */
195 #define v22_W_VCID_OFF 2 /* offset of VC ID */
196 #define v22_W_FLOWSEQ_OFF 4 /* offset of signature sequence number */
197 #define v22_W_FLOWID_OFF 5 /* offset of flow ID */
198 #define v22_W_OCTET_OFF 8 /* offset of octets */
199 #define v22_W_ERRORS_OFF 10 /* offset of error vector */
200 #define v22_W_PATN_OFF 12
201 #define v22_W_L4ID_OFF 12
202 #define v22_W_IPLEN_OFF 14
203 #define v22_W_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
204 #define v22_W_RSSI_OFF 21 /* RSSI (NOTE: RSSI must be negated!) */
205 #define v22_W_STARTT_OFF 24 /* offset of start time, 64 bits */
206 #define v22_W_ENDT_OFF 32 /* offset of end time, 64 bits */
207 #define v22_W_LATVAL_OFF 40 /* offset of latency, 32 bits */
208 #define v22_W_INFO_OFF 54 /* offset of INFO field, 16 LSBs */
209 #define v22_W_DIFFERENTIATOR_OFF 20 /* offset to determine whether */
210 /* eth/802.11, 32 bits */
212 #define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
215 /* Modulation types */
216 #define v22_W_MT_CCKL 0 /* CCK modulation, long preamble */
217 #define v22_W_MT_CCKS 1 /* CCK modulation, short preamble */
218 #define v22_W_MT_OFDM 2 /* OFDM modulation */
220 /* Bits in FRAME_TYPE field */
221 #define v22_W_IS_TCP 0x00000040 /* TCP */
222 #define v22_W_IS_UDP 0x00000010 /* UDP */
223 #define v22_W_IS_ICMP 0x00000020 /* ICMP */
224 #define v22_W_IS_IGMP 0x00000080 /* IGMP */
226 /* Bits in MTYPE field (WLAN only) */
227 #define v22_W_IS_QOS 0x80 /* QoS */
230 #define v22_W_FCS_ERROR 0x0002 /* FCS error flag in error vector */
231 #define v22_W_CRYPTO_ERR 0x1f00 /* RX decrypt error flags */
232 #define v22_W_SIG_ERR 0x0004 /* signature magic byte mismatch */
233 #define v22_W_PAYCHK_ERR 0x0008 /* payload checksum failure */
234 #define v22_W_RETRY_ERR 0x0400 /* excessive retries on TX failure */
236 /* Masks and defines */
237 #define v22_W_IS_RX 0x08 /* TX/RX bit in STATS block */
238 #define v22_W_MT_MASK 0x07 /* modulation type mask */
240 #define v22_W_VCID_MASK 0x01ff /* VC ID is only 9 bits */
242 #define v22_W_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
244 #define v22_W_DIFFERENTIATOR_MASK 0Xf0ff /* mask to differentiate ethernet from */
247 #define v22_W_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted bits */
248 #define v22_W_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted bits */
251 #define v22_W_WEPTYPE 0x0001 /* WEP frame */
252 #define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
253 #define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
254 #define v22_W_MPDU_OF_A_MPDU 0x0400 /* MPDU of A-MPDU */
255 #define v22_W_FIRST_MPDU_OF_A_MPDU 0x0800 /* first MPDU of A-MPDU */
256 #define v22_W_LAST_MPDU_OF_A_MPDU 0x1000 /* last MPDU of A-MPDU */
257 #define v22_W_MSDU_OF_A_MSDU 0x2000 /* MSDU of A-MSDU */
258 #define v22_W_FIRST_MSDU_OF_A_MSDU 0x4000 /* first MSDU of A-MSDU */
259 #define v22_W_LAST_MSDU_OF_A_MSDU 0x8000 /* last MSDU of A-MSDU */
261 /* All aggregation flags */
262 #define v22_W_AGGREGATE_FLAGS \
263 (v22_W_MPDU_OF_A_MPDU | \
264 v22_W_FIRST_MPDU_OF_A_MPDU | \
265 v22_W_LAST_MPDU_OF_A_MPDU | \
266 v22_W_MSDU_OF_A_MSDU | \
267 v22_W_FIRST_MSDU_OF_A_MSDU | \
268 v22_W_LAST_MSDU_OF_A_MSDU)
270 #define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
272 #define v22_W_IS_ETHERNET 0x00100000 /* bits set in frame type if ethernet */
273 #define v22_W_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
275 /* definitions for VW510021 FPGA, WLAN format */
278 8 bytes of stat block
279 plcp stuff (11 bytes plcp + 1 byte pad)
281 remaining 48 bytes of stat block
283 /* offsets in the stats block */
284 #define vVW510021_W_STATS_HEADER_LEN 8 /* length of stats block header at beginning of record data */
285 #define vVW510021_W_STATS_TRAILER_LEN 48 /* length of stats block trailer after the plcp portion*/
286 #define vVW510021_W_STARTT_OFF 0 /* offset of start time, 64 bits */
287 #define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
288 #define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
289 #define vVW510021_W_VALID_OFF 20 /* 2 Bytes with different validity bits */
290 #define vVW510021_W_INFO_OFF 22 /* offset of INFO field, 16 LSBs */
291 #define vVW510021_W_FRAME_TYPE_OFF 24
292 #define vVW510021_W_L4ID_OFF 28
293 #define vVW510021_W_IPLEN_OFF 30 /* offset of IP Total Length field */
294 #define vVW510021_W_FLOWSEQ_OFF 32 /* offset of signature sequence number */
295 #define vVW510021_W_FLOWID_OFF 33 /* offset of flow ID */
296 #define vVW510021_W_LATVAL_OFF 36 /* offset of delay/flowtimestamp, 32b */
297 #define vVW510021_W_DEBUG_OFF 40 /* offset of debug, 16 bits */
298 #define S2_W_FPGA_VERSION_OFF 44 /* offset of fpga version, 16 bits */
299 #define vVW510021_W_MATCH_OFF 47 /* offset of pattern match vector */
301 /* offsets in the header block */
302 #define vVW510021_W_HEADER_LEN 16 /* length of FRAME header */
303 #define vVW510021_W_RXTX_OFF 0 /* rxtx offset, cmd byte of header */
304 #define vVW510021_W_HEADER_VERSION_OFF 9 /* version, 2bytes */
305 #define vVW510021_MSG_LENGTH_OFF 10 /* MSG LENGTH, 2bytes */
306 #define vVW510021_W_DEVICE_TYPE_OFF 8 /* version, 2bytes */
308 /* offsets that occur right after the header */
309 #define vVW510021_W_AFTERHEADER_LEN 8 /* length of STATs info directly after header */
310 #define vVW510021_W_L1P_1_OFF 0 /* offset of 1st byte of layer one info */
311 #define vVW510021_W_L1P_2_OFF 1 /* offset of 2nd byte of layer one info */
312 #define vVW510021_W_MTYPE_OFF vVW510021_W_L1P_2_OFF
313 #define vVW510021_W_PREAMBLE_OFF vVW510021_W_L1P_1_OFF
314 #define vVW510021_W_RSSI_TXPOWER_OFF 2 /* RSSI (NOTE: RSSI must be negated!) */
315 #define vVW510021_W_MSDU_LENGTH_OFF 3 /* 7:0 of length, next byte 11:8 in top 4 bits */
316 #define vVW510021_W_BVCV_VALID_OFF 4 /* BV,CV Determine validaity of bssid and txpower */
317 #define vVW510021_W_VCID_OFF 6 /* offset of VC (client) ID */
318 #define vVW510021_W_PLCP_LENGTH_OFF 12 /* LENGTH field in the plcp header */
320 /* Masks and defines */
321 #define vVW510021_W_IS_BV 0x04 /* BV bit in STATS block */
322 #define vVW510021_W_IS_CV 0x02 /* BV bit in STATS block */
323 #define vVW510021_W_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else 0) */
324 #define vVW510021_W_QOS_VALID 0x4000
325 #define vVW510021_W_HT_VALID 0x2000
326 #define vVW510021_W_L4ID_VALID 0x1000
327 #define vVW510021_W_MOD_SCHEME_MASK 0x3f /* modulation type mask */
328 #define vVW510021_W_SEL_MASK 0x80
329 #define vVW510021_W_WEP_MASK 0x0001
330 #define vVW510021_W_CBW_MASK 0xC0
332 #define vVW510024_W_VCID_MASK 0x03ff /* VC ID is only 10 bits */
334 #define vVW510021_W_MT_SEL_LEGACY 0x00
336 #define vVW510021_W_IS_WEP 0x0001
338 /* L1p byte 1 info */
340 /* Common to Series II and Series III */
342 #define vVW510021_W_IS_LONGPREAMBLE 0x40 /* short/long preamble bit */
343 #define vVW510021_W_IS_LONGGI 0x40 /* short/long guard interval bit */
347 #define vVW510021_W_S2_MCS_INDEX(l1p_1) ((l1p_1) & 0x3f) /* MCS index */
352 * VHT - contains MCS index and number of spatial streams.
353 * The number of spatial streams from the FPGA is zero-based, so we add
356 #define vVW510021_W_S3_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index */
357 #define vVW510021_W_S3_NSS_VHT(l1p_1) (((l1p_1) >> 4 & 0x3) + 1) /* NSS */
360 * HT - contains MCS index
362 #define vVW510021_W_S3_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
364 /* L1p byte 2 info */
366 /* Common to Series II and Series III */
367 #define vVW510021_W_BANDWIDTH_VHT(l1p_2) (((l1p_2) >> 4) & 0xf)
368 /* 3 = 40 MHz, 4 = 80 MHz; what about 20 and 160 MHz? */
371 #define vVW510021_W_S2_PLCP_TYPE(l1p_2) ((l1p_2) & 0x03) /* PLCP type */
374 #define vVW510021_W_S3_PLCP_TYPE(l1p_2) ((l1p_2) & 0x0f) /* PLCP type */
377 #define vVW510021_W_PLCP_LEGACY 0x00 /* pre-HT (11b/a/g) */
378 #define vVW510021_W_PLCP_MIXED 0x01 /* HT, mixed (11n) */
379 #define vVW510021_W_PLCP_GREENFIELD 0x02 /* HT, greenfield (11n) */
380 #define vVW510021_W_PLCP_VHT_MIXED 0x03 /* VHT (11ac) */
382 /* Bits in FRAME_TYPE field */
383 #define vVW510021_W_IS_TCP 0x01000000 /* TCP */
384 #define vVW510021_W_IS_UDP 0x00100000 /* UDP */
385 #define vVW510021_W_IS_ICMP 0x00001000 /* ICMP */
386 #define vVW510021_W_IS_IGMP 0x00010000 /* IGMP */
389 #define vVW510021_W_HEADER_VERSION 0x00
390 #define vVW510021_W_DEVICE_TYPE 0x15
391 #define vVW510021_W_11n_DEVICE_TYPE 0x20
392 #define S2_W_FPGA_VERSION 0x000C
393 #define vVW510021_W_11n_FPGA_VERSION 0x000D
396 #define vVW510021_W_FCS_ERROR 0x01
398 #define vVW510021_W_CRYPTO_ERROR 0x50000
400 /* Info bits are the same as for the VWS10006 FPGA */
402 /* definitions for VW510024 FPGA, wired ethernet format */
405 52 bytes of stats block trailer
407 /* offsets in the stats block */
408 #define vVW510024_E_STATS_LEN 48 /* length of stats block trailer */
409 #define vVW510024_E_MSDU_LENGTH_OFF 0 /* MSDU 16 BITS */
410 #define vVW510024_E_BMCV_VALID_OFF 2 /* BM,CV Determine validITY */
411 #define vVW510024_E_VCID_OFF 2 /* offset of VC (client) ID 13:8, */
413 #define vVW510024_E_STARTT_OFF 4 /* offset of start time, 64 bits */
414 #define vVW510024_E_ENDT_OFF 12 /* offset of end time, 64 bits */
415 #define vVW510024_E_ERRORS_OFF 22 /* offset of error vector */
416 #define vVW510024_E_VALID_OFF 24 /* 2 Bytes with different validity bits */
417 #define vVW510024_E_INFO_OFF 26 /* offset of INFO field, 16 LSBs */
418 #define vVW510024_E_FRAME_TYPE_OFF 28
419 #define vVW510024_E_L4ID_OFF 32
420 #define vVW510024_E_IPLEN_OFF 34
421 #define vVW510024_E_FLOWSEQ_OFF 36 /* offset of signature sequence number */
422 #define vVW510024_E_FLOWID_OFF 37 /* offset of flow ID */
423 #define vVW510024_E_LATVAL_OFF 40 /* offset of delay/flowtimestamp, 32 bits */
424 #define vVW510024_E_FPGA_VERSION_OFF 20 /* offset of fpga version, 16 bits */
425 #define vVW510024_E_MATCH_OFF 51 /* offset of pattern match vector */
427 /* offsets in the header block */
428 #define vVW510024_E_HEADER_LEN vVW510021_W_HEADER_LEN /* length of FRAME header */
429 #define vVW510024_E_RXTX_OFF vVW510021_W_RXTX_OFF /* rxtx offset, cmd byte */
430 #define vVW510024_E_HEADER_VERSION_OFF 16 /* version, 2bytes */
431 #define vVW510024_E_MSG_LENGTH_OFF vVW510021_MSG_LENGTH_OFF /* MSG LENGTH, 2bytes */
432 #define vVW510024_E_DEVICE_TYPE_OFF vVW510021_W_DEVICE_TYPE_OFF /* Device Type, 2bytes */
434 /* Masks and defines */
435 #define vVW510024_E_IS_BV 0x80 /* Bm bit in STATS block */
436 #define vVW510024_E_IS_CV 0x40 /* cV bit in STATS block */
437 #define vVW510024_E_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else force to 0) */
438 #define vVW510024_E_QOS_VALID 0x0000 /** not valid for ethernet **/
439 #define vVW510024_E_L4ID_VALID 0x1000
440 #define vVW510024_E_CBW_MASK 0xC0
442 #define vVW510024_E_VCID_MASK 0x3fff /* VCID is only 14 bits */
444 #define vVW510024_E_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
445 #define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
446 #define vVW510024_E_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
447 #define vVW510024_E_IS_IGMP 0x00010000
448 #define vVW510024_E_IS_VLAN 0x4000
450 #define vVW510024_E_HEADER_VERSION 0x00
451 #define vVW510024_E_DEVICE_TYPE 0x18
452 #define vVW510024_E_FPGA_VERSION 0x0001
454 #define FPGA_VER_NOT_APPLICABLE 0
456 #define UNKNOWN_FPGA 0
459 #define vVW510012_E_FPGA 3
460 #define vVW510024_E_FPGA 4
463 /* the flow signature is:
465 0 Magic Number (0xDD)
466 1 Chassis Number[7:0]
472 7 Flow Sequence Number[7:0]
483 #define SIG_SIZE 16 /* size of signature field, bytes */
484 #define SIG_FID_OFF 4 /* offset of flow ID in signature */
485 #define SIG_FSQ_OFF 7 /* offset of flow seqnum in signature */
486 #define SIG_TS_OFF 8 /* offset of flow seqnum in signature */
490 /*--------------------------------------------------------------------------------------*/
491 /* Per-capture file private data structure */
494 /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
495 /* version number of .vwr file, and are set up by setup_defaults() */
496 guint32 STATS_LEN; /* length of stats block trailer */
497 guint32 STATS_START_OFF; /* STATS OFF AFTER HEADER */
498 guint32 VALID_OFF; /* bit 6 (0x40) is flow-is-valid flag */
499 guint32 MTYPE_OFF; /* offset of modulation type */
500 guint32 VCID_OFF; /* offset of VC ID */
501 guint32 FLOWSEQ_OFF; /* offset of signature sequence number */
502 guint32 FLOWID_OFF; /* offset of flow ID */
503 guint32 OCTET_OFF; /* offset of octets */
504 guint32 ERRORS_OFF; /* offset of error vector */
505 guint32 PATN_OFF; /* offset of pattern match vector */
506 guint32 RSSI_OFF; /* RSSI (NOTE: RSSI must be negated!) */
507 guint32 STARTT_OFF; /* offset of start time, 64 bits */
508 guint32 ENDT_OFF; /* offset of end time, 64 bits */
509 guint32 LATVAL_OFF; /* offset of latency, 32 bits */
510 guint32 INFO_OFF; /* offset of INFO field, 16 bits */
511 guint32 L1P_1_OFF; /* offset 1ST Byte of l1params */
512 guint32 L1P_2_OFF; /* offset 2nd Byte of l1params */
513 guint32 L4ID_OFF; /* LAYER 4 id offset*/
514 guint32 IPLEN_OFF; /* */
515 guint32 PLCP_LENGTH_OFF; /* offset of length field in the PLCP header */
516 guint32 FPGA_VERSION_OFF; /* offset of fpga version field, 16 bits */
517 guint32 HEADER_VERSION_OFF; /* offset of header version, 16 bits */
518 guint32 RXTX_OFF; /* offset of CMD bit, rx or tx */
519 guint32 FRAME_TYPE_OFF;
521 /* other information about the file in question */
522 guint32 MT_10_HALF; /* 10 Mb/s half-duplex */
523 guint32 MT_10_FULL; /* 10 Mb/s full-duplex */
524 guint32 MT_100_HALF; /* 100 Mb/s half-duplex */
525 guint32 MT_100_FULL; /* 100 Mb/s full-duplex */
526 guint32 MT_1G_HALF; /* 1 Gb/s half-duplex */
527 guint32 MT_1G_FULL; /* 1 Gb/s full-duplex */
528 guint32 FCS_ERROR; /* FCS error in frame */
529 guint32 CRYPTO_ERR; /* RX decrypt error flags */
530 guint32 PAYCHK_ERR; /* payload checksum failure */
531 guint32 RETRY_ERR; /* excessive retries on TX failure */
532 guint8 IS_RX; /* TX/RX bit in STATS block */
533 guint8 MT_MASK; /* modulation type mask */
534 guint16 VCID_MASK; /* VC ID might not be a full 16 bits */
535 guint32 FLOW_VALID; /* flow-is-valid flag (else force to 0) */
537 guint32 RX_DECRYPTS; /* RX-frame-was-decrypted bits */
538 guint32 TX_DECRYPTS; /* TX-frame-was-decrypted bits */
539 guint32 FC_PROT_BIT; /* Protected Frame bit in FC1 of frame */
540 guint32 MT_CCKL; /* CCK modulation, long preamble */
541 guint32 MT_CCKS; /* CCK modulation, short preamble */
542 guint32 MT_OFDM; /* OFDM modulation */
543 guint32 FPGA_VERSION;
544 guint32 WEPTYPE; /* frame is WEP */
545 guint32 TKIPTYPE; /* frame is TKIP */
546 guint32 CCMPTYPE; /* frame is CCMP */
556 /* internal utility functions */
557 static int decode_msg(register guint8 *, int *, int *);
558 static guint8 get_ofdm_rate(const guint8 *);
559 static guint8 get_cck_rate(const guint8 *plcp);
560 static void setup_defaults(vwr_t *, guint16);
562 static gboolean vwr_read(wtap *, int *, gchar **, gint64 *);
563 static gboolean vwr_seek_read(wtap *, gint64, struct wtap_pkthdr *phdr,
564 Buffer *, int *, gchar **);
566 static gboolean vwr_read_rec_header(FILE_T, int *, int *, int *, gchar **);
567 static gboolean vwr_process_rec_data(FILE_T fh, int rec_size,
568 struct wtap_pkthdr *phdr, Buffer *buf,
569 vwr_t *vwr, int IS_TX, int *err,
572 static int vwr_get_fpga_version(wtap *, int *, gchar **);
574 static gboolean vwr_read_s1_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
575 const guint8 *, int, int *, gchar **);
576 static gboolean vwr_read_s2_s3_W_rec(vwr_t *, struct wtap_pkthdr *, Buffer *,
577 const guint8 *, int, int, int *,
579 static gboolean vwr_read_rec_data_ethernet(vwr_t *, struct wtap_pkthdr *,
580 Buffer *, const guint8 *, int,
581 int, int *, gchar **);
583 static int find_signature(const guint8 *, int, int, register guint32, register guint8);
584 static guint64 get_signature_ts(const guint8 *, int);
585 static float getRate( guint8 plcpType, guint8 mcsIndex, guint16 rflags, guint8 nss );
587 /* Open a .vwr file for reading */
588 /* This does very little, except setting the wiretap header for a VWR file type */
589 /* and setting the timestamp precision to microseconds. */
591 wtap_open_return_val vwr_open(wtap *wth, int *err, gchar **err_info)
598 fpgaVer = vwr_get_fpga_version(wth, err, err_info);
600 return WTAP_OPEN_ERROR; /* I/O error */
602 if (fpgaVer == UNKNOWN_FPGA) {
603 return WTAP_OPEN_NOT_MINE; /* not a VWR file */
606 /* This is a vwr file */
607 vwr = (vwr_t *)g_malloc0(sizeof(vwr_t));
608 wth->priv = (void *)vwr;
610 vwr->FPGA_VERSION = fpgaVer;
611 /* set the local module options first */
612 setup_defaults(vwr, fpgaVer);
614 wth->snapshot_length = 0;
615 wth->subtype_read = vwr_read;
616 wth->subtype_seek_read = vwr_seek_read;
617 wth->file_tsprec = WTAP_TSPREC_USEC;
618 wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
620 if (fpgaVer == S2_W_FPGA || fpgaVer == S1_W_FPGA || fpgaVer == S3_W_FPGA)
621 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VWR_80211;
622 else if (fpgaVer == vVW510012_E_FPGA || fpgaVer == vVW510024_E_FPGA)
623 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VWR_ETH;
625 return WTAP_OPEN_MINE;
629 /* Read the next packet */
630 /* Note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
631 /* different types; some types, including frame record headers, are followed by */
632 /* variable-length data. */
633 /* A frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
634 /* frame, and a 64-byte statistics block trailer. */
635 /* The PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
637 static gboolean vwr_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
639 vwr_t *vwr = (vwr_t *)wth->priv;
640 int rec_size = 0, IS_TX;
642 /* read the next frame record header in the capture file; if no more frames, return */
643 if (!vwr_read_rec_header(wth->fh, &rec_size, &IS_TX, err, err_info))
644 return FALSE; /* Read error or EOF */
647 * We're past the header; return the offset of the header, not of
648 * the data past the header.
650 *data_offset = (file_tell(wth->fh) - VW_RECORD_HEADER_LENGTH);
652 /* got a frame record; read and process it */
653 if (!vwr_process_rec_data(wth->fh, rec_size, &wth->phdr,
654 wth->frame_buffer, vwr, IS_TX, err, err_info))
657 /* If the per-file encapsulation isn't known, set it to this packet's encapsulation. */
658 /* If it *is* known, and it isn't this packet's encapsulation, set it to */
659 /* WTAP_ENCAP_PER_PACKET, as this file doesn't have a single encapsulation for all */
660 /* packets in the file. */
661 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
662 wth->file_encap = wth->phdr.pkt_encap;
664 if (wth->file_encap != wth->phdr.pkt_encap)
665 wth->file_encap = WTAP_ENCAP_PER_PACKET;
671 /* read a random record in the middle of a file; the start of the record is @ seek_off */
673 static gboolean vwr_seek_read(wtap *wth, gint64 seek_off,
674 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
676 vwr_t *vwr = (vwr_t *)wth->priv;
679 /* first seek to the indicated record header */
680 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
683 /* read in the record header */
684 if (!vwr_read_rec_header(wth->random_fh, &rec_size, &IS_TX, err, err_info))
685 return FALSE; /* Read error or EOF */
687 return vwr_process_rec_data(wth->random_fh, rec_size, phdr, buf,
688 vwr, IS_TX, err, err_info);
691 /* Scan down in the input capture file to find the next frame header. */
692 /* Decode and skip over all non-frame messages that are in the way. */
693 /* Return TRUE on success, FALSE on EOF or error. */
694 /* Also return the frame size in bytes and the "is transmitted frame" flag. */
696 static gboolean vwr_read_rec_header(FILE_T fh, int *rec_size, int *IS_TX, int *err, gchar **err_info)
699 guint8 header[VW_RECORD_HEADER_LENGTH];
703 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
704 /* or if we run out of data. */
705 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
706 /* variable-length item, we read the variable length item out and discard it. */
707 /* If we find a frame, we return (with the header in the passed buffer). */
709 if (!wtap_read_bytes_or_eof(fh, header, VW_RECORD_HEADER_LENGTH, err, err_info))
712 /* Got a header; invoke decode-message function to parse and process it. */
713 /* If the function returns a length, then a frame or variable-length message */
714 /* follows the 16-byte message. */
715 /* If the variable length message is not a frame, simply skip over it. */
716 if ((f_len = decode_msg(header, &v_type, IS_TX)) != 0) {
717 if (f_len > B_SIZE) {
718 *err = WTAP_ERR_BAD_FILE;
719 *err_info = g_strdup_printf("vwr: Invalid message record length %d", f_len);
722 else if (v_type != VT_FRAME) {
723 if (!file_skip(fh, f_len, err))
734 /* Figure out the FPGA version (and also see whether this is a VWR file type. */
735 /* Return FPGA version if it's a known version, UNKNOWN_FPGA if it's not, */
736 /* and -1 on an I/O error. */
738 static int vwr_get_fpga_version(wtap *wth, int *err, gchar **err_info)
740 guint8 rec[B_SIZE]; /* local buffer (holds input record) */
741 guint8 header[VW_RECORD_HEADER_LENGTH];
744 guint8 *s_510006_ptr = NULL;
745 guint8 *s_510024_ptr = NULL;
746 guint8 *s_510012_ptr = NULL; /* stats pointers */
748 guint32 frame_type = 0;
750 guint16 data_length = 0;
751 guint16 fpga_version;
752 int valid_but_empty_file = -1;
754 filePos = file_tell(wth->fh);
756 *err = file_error(wth->fh, err_info);
761 /* Got a frame record; see if it is vwr */
762 /* If we don't get it all, then declare an error, we can't process the frame. */
763 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
764 /* or if we run out of data. */
765 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
766 /* variable-length item, we read the variable length item out and discard it. */
767 /* If we find a frame, we return (with the header in the passed buffer). */
768 while (wtap_read_bytes(wth->fh, header, VW_RECORD_HEADER_LENGTH, err, err_info)) {
769 /* Got a header; invoke decode-message function to parse and process it. */
770 /* If the function returns a length, then a frame or variable-length message */
771 /* follows the 16-byte message. */
772 /* If the variable length message is not a frame, simply skip over it. */
773 if ((f_len = decode_msg(header, &v_type, NULL)) != 0) {
774 if (f_len > B_SIZE) {
775 /* Treat this here as an indication that the file probably */
776 /* isn't a vwr file. */
779 else if (v_type != VT_FRAME) {
780 if (file_seek(wth->fh, f_len, SEEK_CUR, err) < 0)
782 else if (v_type == VT_CPMSG)
783 valid_but_empty_file = 1;
787 /* Got a frame record; read over entire record (frame + trailer) into a local buffer */
788 /* If we don't get it all, assume this isn't a vwr file */
789 if (!wtap_read_bytes(wth->fh, rec, rec_size, err, err_info)) {
790 if (*err == WTAP_ERR_SHORT_READ)
791 return UNKNOWN_FPGA; /* short read - not a vwr file */
796 /* I'll grab the bytes where the Ethernet "octets" field should be and the bytes where */
797 /* the 802.11 "octets" field should be. Then if I do rec_size - octets - */
798 /* size_of_stats_block and it's 0, I can select the correct type. */
799 /* octets + stats_len = rec_size only when octets have been incremented to nearest */
800 /* number divisible by 4. */
802 /* First check for series I WLAN since the check is more rigorous. */
803 if (rec_size > v22_W_STATS_LEN) {
804 s_510006_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to 510006 WLAN */
807 data_length = pntoh16(&s_510006_ptr[v22_W_OCTET_OFF]);
809 while (((data_length + i) % 4) != 0)
812 frame_type = pntoh32(&s_510006_ptr[v22_W_FRAME_TYPE_OFF]);
814 if (rec_size == (data_length + v22_W_STATS_LEN + i) && (frame_type & v22_W_IS_80211) == 0x1000000) {
815 fpga_version = S1_W_FPGA;
819 /* Next for the series I Ethernet */
820 if ((rec_size > v22_E_STATS_LEN) && (fpga_version == 1000)) {
821 s_510012_ptr = &(rec[rec_size - v22_E_STATS_LEN]); /* point to 510012 enet */
823 data_length = pntoh16(&s_510012_ptr[v22_E_OCTET_OFF]);
825 while (((data_length + i) % 4) != 0)
828 if (rec_size == (data_length + v22_E_STATS_LEN + i))
829 fpga_version = vVW510012_E_FPGA;
833 /* Next the series II WLAN */
834 if ((rec_size > vVW510021_W_STATS_TRAILER_LEN) && (fpga_version == 1000)) {
837 if ((header[8] == 48) || (header[8] == 61) || (header[8] == 68))
838 fpga_version = S3_W_FPGA;
840 data_length = (256 * (rec[vVW510021_W_MSDU_LENGTH_OFF + 1] & 0x1f)) + rec[vVW510021_W_MSDU_LENGTH_OFF];
843 while (((data_length + i) % 4) != 0)
846 /*the 12 is from the 12 bytes of plcp header */
847 if (rec_size == (data_length + vVW510021_W_STATS_TRAILER_LEN +vVW510021_W_AFTERHEADER_LEN+12+i))
848 fpga_version = S2_W_FPGA;
852 /* Finally the Series II Ethernet */
853 if ((rec_size > vVW510024_E_STATS_LEN) && (fpga_version == 1000)) {
854 s_510024_ptr = &(rec[rec_size - vVW510024_E_STATS_LEN]); /* point to 510024 ENET */
855 data_length = pntoh16(&s_510024_ptr[vVW510024_E_MSDU_LENGTH_OFF]);
858 while (((data_length + i) % 4) != 0)
861 if (rec_size == (data_length + vVW510024_E_STATS_LEN + i))
862 fpga_version = vVW510024_E_FPGA;
864 if (fpga_version != 1000)
866 /* reset the file position offset */
867 if (file_seek (wth->fh, filePos, SEEK_SET, err) == -1) {
870 /* We found an FPGA that works */
877 /* Is this a valid but empty file? If so, claim it's the S3_W_FPGA FPGA. */
878 if (valid_but_empty_file > 0)
881 if (*err == WTAP_ERR_SHORT_READ)
882 return UNKNOWN_FPGA; /* short read - not a vwr file */
886 /* Copy the actual packet data from the capture file into the target data block. */
887 /* The packet is constructed as a 38-byte VeriWave metadata header plus the raw */
890 static gboolean vwr_read_s1_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
891 Buffer *buf, const guint8 *rec, int rec_size,
892 int *err, gchar **err_info)
895 int bytes_written = 0; /* bytes output to buf so far */
896 const guint8 *s_ptr, *m_ptr; /* stats pointer */
897 guint16 msdu_length, actual_octets; /* octets in frame */
898 guint16 plcp_hdr_len; /* PLCP header length */
900 guint8 m_type; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
902 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
905 guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
906 guint64 end_time; /* end time */
907 guint32 info; /* INFO/ERRORS fields in stats blk */
908 gint8 rssi; /* RSSI, signed 8-bit number */
909 int f_tx; /* flag: if set, is a TX frame */
910 guint8 plcp_type, mcs_index, nss; /* PLCP type 0: Legacy, 1: Mixed, 2: Green field, 3: VHT Mixed */
911 guint16 vc_id, ht_len=0; /* VC ID, total ip length */
912 guint flow_id; /* flow ID */
913 guint32 d_time, errors; /* packet duration & errors */
914 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
915 guint64 sig_ts; /* 32 LSBs of timestamp in signature */
917 guint16 vw_flags; /* VeriWave-specific packet flags */
920 * The record data must be large enough to hold the statistics trailer.
922 if (rec_size < v22_W_STATS_LEN) {
923 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
924 rec_size, v22_W_STATS_LEN);
925 *err = WTAP_ERR_BAD_FILE;
929 /* Calculate the start of the statistics block in the buffer */
930 /* Also get a bunch of fields from the stats block */
931 s_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to it */
932 m_type = s_ptr[v22_W_MTYPE_OFF] & 0x7;
933 f_tx = !(s_ptr[v22_W_MTYPE_OFF] & 0x8);
934 actual_octets = pntoh16(&s_ptr[v22_W_OCTET_OFF]);
935 vc_id = pntoh16(&s_ptr[v22_W_VCID_OFF]) & 0x3ff;
936 flow_seq = s_ptr[v22_W_FLOWSEQ_OFF];
938 latency = (guint32)pcorey48tohll(&s_ptr[v22_W_LATVAL_OFF]);
940 flow_id = pntoh16(&s_ptr[v22_W_FLOWID_OFF+1]); /* only 16 LSBs kept */
941 errors = pntoh16(&s_ptr[v22_W_ERRORS_OFF]);
943 info = pntoh16(&s_ptr[v22_W_INFO_OFF]);
944 rssi = (s_ptr[v22_W_RSSI_OFF] & 0x80) ? (-1 * (s_ptr[v22_W_RSSI_OFF] & 0x7f)) : s_ptr[v22_W_RSSI_OFF];
947 * Sanity check the octets field to determine if it's greater than
948 * the packet data available in the record - i.e., the record size
949 * minus the length of the statistics block.
951 * Report an error if it is.
953 if (actual_octets > rec_size - v22_W_STATS_LEN) {
954 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
956 *err = WTAP_ERR_BAD_FILE;
960 /* Decode OFDM or CCK PLCP header and determine rate and short preamble flag. */
961 /* The SIGNAL byte is always the first byte of the PLCP header in the frame. */
964 if (m_type == vwr->MT_OFDM)
965 mcs_index = get_ofdm_rate(rec);
966 else if ((m_type == vwr->MT_CCKL) || (m_type == vwr->MT_CCKS))
967 mcs_index = get_cck_rate(rec);
970 rflags = (m_type == vwr->MT_CCKS) ? FLAGS_SHORTPRE : 0;
971 /* Calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK. */
972 /* Note that the number of octets in the frame also varies depending on OFDM/CCK, */
973 /* because the PLCP header is prepended to the actual MPDU. */
974 plcp_hdr_len = (m_type == vwr->MT_OFDM) ? 4 : 6;
975 if (actual_octets >= plcp_hdr_len)
976 actual_octets -= plcp_hdr_len;
978 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header)",
979 actual_octets, plcp_hdr_len);
980 *err = WTAP_ERR_BAD_FILE;
983 m_ptr = &rec[plcp_hdr_len];
984 msdu_length = actual_octets;
987 * The MSDU length includes the FCS.
989 * The packet data does *not* include the FCS - it's just 4 bytes
990 * of junk - so we have to remove it.
992 * We'll be stripping off an FCS (?), so make sure we have at
993 * least 4 octets worth of FCS.
995 if (actual_octets < 4) {
996 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header and 4 bytes of FCS)",
997 actual_octets, plcp_hdr_len);
998 *err = WTAP_ERR_BAD_FILE;
1003 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1004 /* 64-bit times are "Corey-endian" */
1005 s_time = pcoreytohll(&s_ptr[v22_W_STARTT_OFF]);
1006 e_time = pcoreytohll(&s_ptr[v22_W_ENDT_OFF]);
1008 /* find the packet duration (difference between start and end times) */
1009 d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
1011 /* also convert the packet start time to seconds and microseconds */
1012 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1013 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1014 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1016 /* also convert the packet end time to seconds and microseconds */
1017 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1019 /* extract the 32 LSBs of the signature timestamp field from the data block*/
1020 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
1021 sig_off = find_signature(m_ptr, rec_size - 6, pay_off, flow_id, flow_seq);
1022 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - v22_W_STATS_LEN)))
1023 sig_ts = get_signature_ts(m_ptr, sig_off);
1028 * Fill up the per-packet header.
1030 * We also zero out 16 bytes PLCP header and 1 byte of L1P for user
1033 * XXX - for S1, do we even have that? The current Veriwave dissector
1034 * just blindly assumes there's a 17-byte blob before the 802.11
1035 * header, which is why we fill in those extra zero bytes.
1037 * We include the length of the metadata headers in the packet lengths.
1039 * The maximum value of actual_octets is 65535, which, even after
1040 * adding the lengths of the metadata headers, is less than
1041 * WTAP_MAX_PACKET_SIZE will ever be, so we don't need to check it.
1043 phdr->len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
1044 phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
1046 phdr->ts.secs = (time_t)s_sec;
1047 phdr->ts.nsecs = (int)(s_usec * 1000);
1048 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1050 phdr->rec_type = REC_TYPE_PACKET;
1051 phdr->presence_flags = WTAP_HAS_TS;
1053 ws_buffer_assure_space(buf, phdr->caplen);
1054 data_ptr = ws_buffer_start_ptr(buf);
1057 * Generate and copy out the common metadata headers,
1058 * set the port type to 0 (WLAN).
1060 * All values are copied out in little-endian byte order.
1062 phtoles(&data_ptr[bytes_written], 0); /* port_type */
1064 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
1066 phtoles(&data_ptr[bytes_written], msdu_length);
1068 phtolel(&data_ptr[bytes_written], flow_id);
1070 phtoles(&data_ptr[bytes_written], vc_id);
1072 phtoles(&data_ptr[bytes_written], flow_seq);
1074 if (!f_tx && sig_ts != 0) {
1075 phtolel(&data_ptr[bytes_written], latency);
1077 phtolel(&data_ptr[bytes_written], 0);
1080 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
1082 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
1084 phtolell(&data_ptr[bytes_written], end_time);
1086 phtolel(&data_ptr[bytes_written], d_time);
1090 * Generate and copy out the WLAN metadata headers.
1092 * All values are copied out in little-endian byte order.
1094 phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
1096 phtoles(&data_ptr[bytes_written], rflags);
1098 if (m_type == vwr->MT_OFDM) {
1099 phtoles(&data_ptr[bytes_written], CHAN_OFDM);
1101 phtoles(&data_ptr[bytes_written], CHAN_CCK);
1104 phyRate = (guint16)(getRate(plcp_type, mcs_index, rflags, nss) * 10);
1105 phtoles(&data_ptr[bytes_written], phyRate);
1107 data_ptr[bytes_written] = plcp_type;
1109 data_ptr[bytes_written] = mcs_index;
1111 data_ptr[bytes_written] = nss;
1113 data_ptr[bytes_written] = rssi;
1115 /* antennae b, c, d signal power */
1116 data_ptr[bytes_written] = 100;
1118 data_ptr[bytes_written] = 100;
1120 data_ptr[bytes_written] = 100;
1123 data_ptr[bytes_written] = 0;
1126 /* fill in the VeriWave flags field */
1129 vw_flags |= VW_FLAGS_TXF;
1130 if (errors & vwr->FCS_ERROR)
1131 vw_flags |= VW_FLAGS_FCSERR;
1132 if (!f_tx && (errors & vwr->CRYPTO_ERR))
1133 vw_flags |= VW_FLAGS_DCRERR;
1134 if (!f_tx && (errors & vwr->RETRY_ERR))
1135 vw_flags |= VW_FLAGS_RETRERR;
1136 if (info & vwr->WEPTYPE)
1137 vw_flags |= VW_FLAGS_IS_WEP;
1138 else if (info & vwr->TKIPTYPE)
1139 vw_flags |= VW_FLAGS_IS_TKIP;
1140 else if (info & vwr->CCMPTYPE)
1141 vw_flags |= VW_FLAGS_IS_CCMP;
1142 phtoles(&data_ptr[bytes_written], vw_flags);
1145 phtoles(&data_ptr[bytes_written], ht_len);
1147 phtoles(&data_ptr[bytes_written], info);
1149 phtolel(&data_ptr[bytes_written], errors);
1153 * No VHT, no VHT NDP flag, so just zero.
1155 * XXX - is this supposed to be the RX L1 info, i.e. the "1 byte of L1P
1156 * for user position"?
1158 data_ptr[bytes_written] = 0;
1162 * XXX - put a PLCP header here? That's what's done for S3.
1164 memset(&data_ptr[bytes_written], 0, 16);
1165 bytes_written += 16;
1168 * Finally, copy the whole MAC frame to the packet buffer as-is.
1169 * This does not include the PLCP; the MPDU starts at 4 or 6
1170 * depending on OFDM/CCK.
1171 * This also does not include the last 4 bytes, as those don't
1172 * contain an FCS, they just contain junk.
1174 memcpy(&data_ptr[bytes_written], &rec[plcp_hdr_len], actual_octets);
1180 static gboolean vwr_read_s2_s3_W_rec(vwr_t *vwr, struct wtap_pkthdr *phdr,
1181 Buffer *buf, const guint8 *rec, int rec_size,
1182 int IS_TX, int *err, gchar **err_info)
1185 int bytes_written = 0; /* bytes output to buf so far */
1186 register int i; /* temps */
1187 const guint8 *s_start_ptr,*s_trail_ptr, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
1188 guint32 msdu_length, actual_octets; /* octets in frame */
1189 guint8 l1p_1,l1p_2, plcp_type, mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
1191 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1193 guint64 latency = LL_ZERO;
1194 guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
1195 guint64 end_time; /* end time */
1196 guint16 info; /* INFO/ERRORS fields in stats blk */
1198 gint8 rssi[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1199 int f_tx; /* flag: if set, is a TX frame */
1200 guint16 vc_id, ht_len=0; /* VC ID , total ip length*/
1201 guint32 flow_id, d_time; /* flow ID, packet duration*/
1202 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1203 guint64 sig_ts, tsid; /* 32 LSBs of timestamp in signature */
1204 guint16 chanflags = 0; /* channel flags for WLAN metadata header */
1205 guint16 radioflags = 0; /* flags for WLAN metadata header */
1206 guint64 delta_b; /* Used for calculating latency */
1208 guint16 vw_flags; /* VeriWave-specific packet flags */
1209 guint8 vht_ndp_flag = 0;
1212 * The record data must be large enough to hold the statistics header,
1213 * the PLCP, and the statistics trailer.
1215 if ((guint)rec_size < vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1216 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1218 vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1219 *err = WTAP_ERR_BAD_FILE;
1223 /* Calculate the start of the statistics blocks in the buffer */
1224 /* Also get a bunch of fields from the stats blocks */
1225 s_start_ptr = &(rec[0]); /* point to stats header */
1226 s_trail_ptr = &(rec[rec_size - vVW510021_W_STATS_TRAILER_LEN]); /* point to stats trailer */
1228 /* L1p info is different for series III and for Series II - need to check */
1229 l1p_1 = s_start_ptr[vVW510021_W_L1P_1_OFF];
1230 l1p_2 = s_start_ptr[vVW510021_W_L1P_2_OFF];
1231 if (vwr->FPGA_VERSION == S2_W_FPGA)
1233 mcs_index = vVW510021_W_S2_MCS_INDEX(l1p_1);
1234 plcp_type = vVW510021_W_S2_PLCP_TYPE(l1p_2);
1235 /* we do the range checks at the end before copying the values
1236 into the wtap header */
1237 msdu_length = ((s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF+1] & 0x1f) << 8)
1238 + s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF];
1240 vc_id = pntoh16(&s_start_ptr[vVW510021_W_VCID_OFF]);
1243 rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
1244 -1 * (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f) :
1245 s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f;
1249 rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
1250 (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF]- 256) :
1251 s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF];
1259 /* XXX - S2 claims to have 11 bytes of PLCP and 1 byte of pad */
1260 plcp_ptr = &(rec[8]);
1264 /* XXX - what indicates which packets include the FCS? */
1265 radioflags |= FLAGS_FCS;
1266 plcp_type = vVW510021_W_S3_PLCP_TYPE(l1p_2);
1267 if (plcp_type == vVW510021_W_PLCP_VHT_MIXED)
1270 mcs_index = vVW510021_W_S3_MCS_INDEX_VHT(l1p_1);
1271 nss = vVW510021_W_S3_NSS_VHT(l1p_1);
1276 mcs_index = vVW510021_W_S3_MCS_INDEX_HT(l1p_1);
1280 /*** Extract NDP Flag if it is a received frame ***/
1282 vht_ndp_flag = s_start_ptr[8];
1285 msdu_length = pntoh24(&s_start_ptr[9]);
1286 vc_id = pntoh16(&s_start_ptr[14]) & vVW510024_W_VCID_MASK;
1287 for (i = 0; i < 4; i++)
1291 rssi[i] = (s_start_ptr[4+i] & 0x80) ? -1 * (s_start_ptr[4+i] & 0x7f) : s_start_ptr[4+i] & 0x7f;
1295 rssi[i] = (s_start_ptr[4+i] >= 128) ? (s_start_ptr[4+i] - 256) : s_start_ptr[4+i];
1299 /*** 16 bytes of PLCP header + 1 byte of L1P for user position ***/
1300 /* XXX - S3 claims to have 16 bytes of stats block and 16 bytes of
1301 *something*. Are those 16 bytes the PLCP? */
1302 plcp_ptr = &(rec[16]);
1304 actual_octets = msdu_length;
1307 * Sanity check the octets field to determine if it's greater than
1308 * the packet data available in the record - i.e., the record size
1309 * minus the sum of (length of statistics header + PLCP) and
1310 * (length of statistics trailer).
1312 * Report an error if it is.
1314 if (actual_octets > rec_size - (vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN)) {
1315 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1317 *err = WTAP_ERR_BAD_FILE;
1322 flow_seq = s_trail_ptr[vVW510021_W_FLOWSEQ_OFF];
1324 latency = 0x00000000; /* clear latency */
1325 flow_id = pntoh24(&s_trail_ptr[vVW510021_W_FLOWID_OFF]); /* all 24 bits valid */
1326 /* For tx latency is duration, for rx latency is timestamp */
1327 /* Get 48-bit latency value */
1328 tsid = pcorey48tohll(&s_trail_ptr[vVW510021_W_LATVAL_OFF]);
1330 errors = pntoh32(&s_trail_ptr[vVW510021_W_ERRORS_OFF]);
1331 info = pntoh16(&s_trail_ptr[vVW510021_W_INFO_OFF]);
1332 if ((info & v22_W_AGGREGATE_FLAGS) != 0)
1333 /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
1334 ht_len = pletoh16(&s_start_ptr[vwr->PLCP_LENGTH_OFF]);
1337 /* decode OFDM or CCK PLCP header and determine rate and short preamble flag */
1338 /* the SIGNAL byte is always the first byte of the PLCP header in the frame */
1339 if (plcp_type == vVW510021_W_PLCP_LEGACY){
1341 * From IEEE Std 802.11-2012:
1343 * According to section 17.2.2 "PPDU format", the PLCP header
1344 * for the High Rate DSSS PHY (11b) has a SIGNAL field that's
1345 * 8 bits, followed by a SERVICE field that's 8 bits, followed
1346 * by a LENGTH field that's 16 bits, followed by a CRC field
1347 * that's 16 bits. The PSDU follows it. Section 17.2.3 "PPDU
1348 * field definitions" describes those fields.
1350 * According to sections 18.3.2 "PLCP frame format" and 18.3.4
1351 * "SIGNAL field", the PLCP for the OFDM PHY (11a) has a SIGNAL
1352 * field that's 24 bits, followed by a service field that's
1353 * 16 bits, followed by the PSDU. Section 18.3.5.2 "SERVICE
1354 * field" describes the SERVICE field.
1356 * According to section 19.3.2 "PPDU format", the frames for the
1357 * Extended Rate PHY (11g) either extend the 11b format, using
1358 * additional bits in the SERVICE field, or extend the 11a
1361 if (mcs_index < 4) {
1362 chanflags |= CHAN_CCK;
1365 chanflags |= CHAN_OFDM;
1368 else if (plcp_type == vVW510021_W_PLCP_MIXED) {
1370 * According to section 20.3.2 "PPDU format", the HT-mixed
1371 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
1372 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
1373 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
1376 * This means that the first octet of HT-SIG is at
1377 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
1379 * 0x80 is the CBW 20/40 bit of HT-SIG.
1381 /* set the appropriate flags to indicate HT mode and CB */
1382 radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[3] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
1383 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1384 chanflags |= CHAN_OFDM;
1386 else if (plcp_type == vVW510021_W_PLCP_GREENFIELD) {
1388 * According to section 20.3.2 "PPDU format", the HT-greenfield
1389 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
1392 * This means that the first octet of HT-SIG is at
1393 * plcp_ptr[0], as there's no L-SIG field to skip.
1395 * 0x80 is the CBW 20/40 bit of HT-SIG.
1397 /* set the appropriate flags to indicate HT mode and CB */
1398 radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[0] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
1399 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1400 chanflags |= CHAN_OFDM;
1402 else if (plcp_type == vVW510021_W_PLCP_VHT_MIXED) {
1404 * According to section 22.3.2 "VHTPPDU format" of IEEE Std
1405 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
1406 * (L-SIG), which looks like an 11a SIGNAL field, followed by
1407 * a VHT Signal A field (VHT-SIG-A) described in section
1408 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
1409 * between it and a VHT Signal B field (VHT-SIG-B) described
1410 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
1413 guint8 SBW = vVW510021_W_BANDWIDTH_VHT(l1p_2);
1414 radioflags |= FLAGS_CHAN_VHT | ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1415 chanflags |= CHAN_OFDM;
1417 radioflags |= FLAGS_CHAN_40MHZ;
1419 radioflags |= FLAGS_CHAN_80MHZ;
1422 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1423 /* 64-bit times are "Corey-endian" */
1424 s_time = pcoreytohll(&s_trail_ptr[vVW510021_W_STARTT_OFF]);
1425 e_time = pcoreytohll(&s_trail_ptr[vVW510021_W_ENDT_OFF]);
1427 /* find the packet duration (difference between start and end times) */
1428 d_time = (guint32)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
1430 /* also convert the packet start time to seconds and microseconds */
1431 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1432 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1433 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1435 /* also convert the packet end time to seconds and microseconds */
1436 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1438 /* extract the 32 LSBs of the signature timestamp field */
1439 m_ptr = &(rec[8+12]);
1440 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
1441 sig_off = find_signature(m_ptr, rec_size - 20, pay_off, flow_id, flow_seq);
1442 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= (rec_size - vVW510021_W_STATS_TRAILER_LEN)))
1443 sig_ts = get_signature_ts(m_ptr, sig_off);
1447 /* Set latency based on rx/tx and signature timestamp */
1449 if (tsid < s_time) {
1450 latency = s_time - tsid;
1452 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1453 /* we look for a large difference between l_time and s_time. */
1454 delta_b = tsid - s_time;
1455 if (delta_b > 0x10000000)
1463 * Fill up the per-packet header.
1465 * We also copy over 16 bytes of PLCP header + 1 byte of L1P for user
1468 * XXX - for S2, we don't have 16 bytes of PLCP header; do we have
1469 * the 1 byte of L1P? The current Veriwave dissector just blindly
1470 * assumes there's a 17-byte blob before the 802.11 header.
1472 * We include the length of the metadata headers in the packet lengths.
1474 phdr->len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
1475 phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + 1 + 16 + actual_octets;
1476 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
1478 * Probably a corrupt capture file; return an error,
1479 * so that our caller doesn't blow up trying to allocate
1480 * space for an immensely-large packet.
1482 *err_info = g_strdup_printf("vwr: File has %u-byte packet, bigger than maximum of %u",
1483 phdr->caplen, WTAP_MAX_PACKET_SIZE);
1484 *err = WTAP_ERR_BAD_FILE;
1488 phdr->ts.secs = (time_t)s_sec;
1489 phdr->ts.nsecs = (int)(s_usec * 1000);
1490 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1492 phdr->rec_type = REC_TYPE_PACKET;
1493 phdr->presence_flags = WTAP_HAS_TS;
1495 ws_buffer_assure_space(buf, phdr->caplen);
1496 data_ptr = ws_buffer_start_ptr(buf);
1499 * Generate and copy out the common metadata headers,
1500 * set the port type to 0 (WLAN).
1502 * All values are copied out in little-endian byte order.
1504 /*** msdu_length = msdu_length + 16; ***/
1505 phtoles(&data_ptr[bytes_written], 0); /* port_type */
1507 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
1509 phtoles(&data_ptr[bytes_written], msdu_length);
1511 phtolel(&data_ptr[bytes_written], flow_id);
1513 phtoles(&data_ptr[bytes_written], vc_id);
1515 phtoles(&data_ptr[bytes_written], flow_seq);
1517 if (!f_tx && sig_ts != 0) {
1518 phtolel(&data_ptr[bytes_written], latency);
1520 phtolel(&data_ptr[bytes_written], 0);
1523 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
1525 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
1527 phtolell(&data_ptr[bytes_written], end_time);
1529 phtolel(&data_ptr[bytes_written], d_time);
1533 * Generate and copy out the WLAN metadata headers.
1535 * All values are copied out in little-endian byte order.
1537 phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
1539 if (info & vVW510021_W_IS_WEP)
1540 radioflags |= FLAGS_WEP;
1541 if (!(l1p_1 & vVW510021_W_IS_LONGPREAMBLE) && (plcp_type == vVW510021_W_PLCP_LEGACY))
1542 radioflags |= FLAGS_SHORTPRE;
1543 phtoles(&data_ptr[bytes_written], radioflags);
1545 phtoles(&data_ptr[bytes_written], chanflags);
1547 phyRate = (guint16)(getRate(plcp_type, mcs_index, radioflags, nss) * 10);
1548 phtoles(&data_ptr[bytes_written], phyRate);
1551 /*** If received frame populate the ndp_flag in the same byte as plcp_type***/
1554 plcp_type = vht_ndp_flag + plcp_type;
1557 data_ptr[bytes_written] = plcp_type;
1560 data_ptr[bytes_written] = mcs_index;
1563 data_ptr[bytes_written] = nss;
1565 data_ptr[bytes_written] = rssi[0];
1567 data_ptr[bytes_written] = rssi[1];
1569 data_ptr[bytes_written] = rssi[2];
1571 data_ptr[bytes_written] = rssi[3];
1574 data_ptr[bytes_written] = 0;
1577 /* fill in the VeriWave flags field */
1580 vw_flags |= VW_FLAGS_TXF;
1581 if (errors & 0x1f) /* If any error is flagged, then set the FCS error bit */
1582 vw_flags |= VW_FLAGS_FCSERR;
1583 if (!f_tx && (errors & vwr->CRYPTO_ERR))
1584 vw_flags |= VW_FLAGS_DCRERR;
1585 if (!f_tx && (errors & vwr->RETRY_ERR))
1586 vw_flags |= VW_FLAGS_RETRERR;
1587 if (info & vwr->WEPTYPE)
1588 vw_flags |= VW_FLAGS_IS_WEP;
1589 else if (info & vwr->TKIPTYPE)
1590 vw_flags |= VW_FLAGS_IS_TKIP;
1591 else if (info & vwr->CCMPTYPE)
1592 vw_flags |= VW_FLAGS_IS_CCMP;
1593 phtoles(&data_ptr[bytes_written], vw_flags);
1596 phtoles(&data_ptr[bytes_written], ht_len);
1598 phtoles(&data_ptr[bytes_written], info);
1600 phtolel(&data_ptr[bytes_written], errors);
1604 * XXX - is this supposed to be the RX L1 info, i.e. the "1 byte of L1P
1605 * for user position"?
1608 data_ptr[bytes_written] = vht_ndp_flag;
1610 data_ptr[bytes_written] = 0;
1617 * XXX - shouldn't that use plcp_ptr?
1619 * XXX - what about S2, where we don't have 16 bytes of PLCP?
1621 memcpy(&data_ptr[bytes_written], &rec[16], 16);
1622 bytes_written += 16;
1625 * Finally, copy the whole MAC frame to the packet buffer as-is.
1626 * This does not include the stats header or the PLCP header.
1628 memcpy(&data_ptr[bytes_written], &rec[vwr->MPDU_OFF], actual_octets);
1633 /* read an Ethernet packet */
1634 /* Copy the actual packet data from the capture file into the target data block. */
1635 /* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
1638 static gboolean vwr_read_rec_data_ethernet(vwr_t *vwr, struct wtap_pkthdr *phdr,
1639 Buffer *buf, const guint8 *rec,
1640 int rec_size, int IS_TX, int *err,
1644 int bytes_written = 0; /* bytes output to buf so far */
1645 const guint8 *s_ptr, *m_ptr; /* stats and MPDU pointers */
1646 guint16 msdu_length, actual_octets; /* octets in frame */
1647 guint flow_seq; /* seqnum */
1648 guint64 s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1650 guint32 latency = 0;
1651 guint64 start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
1652 guint64 end_time; /* end time */
1654 guint16 info, validityBits; /* INFO/ERRORS fields in stats */
1656 guint16 vc_id; /* VC ID, total (incl of aggregates) */
1657 guint32 flow_id, d_time; /* packet duration */
1658 int f_flow; /* flags: flow valid */
1659 guint32 frame_type; /* frame type field */
1660 int mac_len, sig_off, pay_off; /* MAC header len, signature offset */
1661 /* XXX - the code here fetched tsid, but never used it! */
1662 guint64 sig_ts/*, tsid*/; /* 32 LSBs of timestamp in signature */
1663 guint64 delta_b; /* Used for calculating latency */
1664 guint16 vw_flags; /* VeriWave-specific packet flags */
1666 if ((guint)rec_size < vwr->STATS_LEN) {
1667 *err_info = g_strdup_printf("vwr: Invalid record length %d (must be at least %u)", rec_size, vwr->STATS_LEN);
1668 *err = WTAP_ERR_BAD_FILE;
1672 /* Calculate the start of the statistics block in the buffer. */
1673 /* Also get a bunch of fields from the stats block. */
1674 m_ptr = &(rec[0]); /* point to the data block */
1675 s_ptr = &(rec[rec_size - vwr->STATS_LEN]); /* point to the stats block */
1677 msdu_length = pntoh16(&s_ptr[vwr->OCTET_OFF]);
1678 actual_octets = msdu_length;
1681 * Sanity check the octets field to determine if it's greater than
1682 * the packet data available in the record - i.e., the record size
1683 * minus the length of the statistics block.
1685 * Report an error if it is.
1687 if (actual_octets > rec_size - vwr->STATS_LEN) {
1688 *err_info = g_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1690 *err = WTAP_ERR_BAD_FILE;
1694 * The maximum value of actual_octets is 65535, which, even after
1695 * adding the lengths of the metadata headers, is less than
1696 * WTAP_MAX_PACKET_SIZE will ever be, so we don't need to check it.
1699 vc_id = pntoh16(&s_ptr[vwr->VCID_OFF]) & vwr->VCID_MASK;
1700 flow_seq = s_ptr[vwr->FLOWSEQ_OFF];
1701 frame_type = pntoh32(&s_ptr[vwr->FRAME_TYPE_OFF]);
1703 if (vwr->FPGA_VERSION == vVW510024_E_FPGA) {
1704 validityBits = pntoh16(&s_ptr[vwr->VALID_OFF]);
1705 f_flow = validityBits & vwr->FLOW_VALID;
1707 mac_len = (validityBits & vwr->IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
1710 errors = pntoh16(&s_ptr[vwr->ERRORS_OFF]);
1713 f_flow = s_ptr[vwr->VALID_OFF] & vwr->FLOW_VALID;
1714 mac_len = (frame_type & vwr->IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
1717 /* for older fpga errors is only represented by 16 bits) */
1718 errors = pntoh16(&s_ptr[vwr->ERRORS_OFF]);
1721 info = pntoh16(&s_ptr[vwr->INFO_OFF]);
1723 flow_id = pntoh24(&s_ptr[vwr->FLOWID_OFF]);
1726 /* For tx latency is duration, for rx latency is timestamp. */
1727 /* Get 64-bit latency value. */
1728 tsid = pcorey48tohll(&s_ptr[vwr->LATVAL_OFF]);
1731 l4id = pntoh16(&s_ptr[vwr->L4ID_OFF]);
1734 * The MSDU length includes the FCS.
1736 * The packet data does *not* include the FCS - it's just 4 bytes
1737 * of junk - so we have to remove it.
1739 * We'll be stripping off an FCS (?), so make sure we have at
1740 * least 4 octets worth of FCS.
1742 if (actual_octets < 4) {
1743 *err_info = g_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
1745 *err = WTAP_ERR_BAD_FILE;
1750 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1751 /* 64-bit times are "Corey-endian" */
1752 s_time = pcoreytohll(&s_ptr[vwr->STARTT_OFF]);
1753 e_time = pcoreytohll(&s_ptr[vwr->ENDT_OFF]);
1755 /* find the packet duration (difference between start and end times) */
1756 d_time = (guint32)((e_time - s_time)); /* find diff, leaving in nsec for Ethernet */
1758 /* also convert the packet start time to seconds and microseconds */
1759 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1760 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1761 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1763 /* also convert the packet end time to seconds and microseconds */
1764 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1766 if (frame_type & vwr->IS_TCP) /* signature offset for TCP frame */
1768 pay_off = mac_len + 40;
1770 else if (frame_type & vwr->IS_UDP) /* signature offset for UDP frame */
1772 pay_off = mac_len + 28;
1774 else if (frame_type & vwr->IS_ICMP) /* signature offset for ICMP frame */
1776 pay_off = mac_len + 24;
1778 else if (frame_type & vwr->IS_IGMP) /* signature offset for IGMPv2 frame */
1780 pay_off = mac_len + 28;
1782 else /* signature offset for raw IP frame */
1784 pay_off = mac_len + 20;
1787 sig_off = find_signature(m_ptr, rec_size, pay_off, flow_id, flow_seq);
1788 if ((m_ptr[sig_off] == 0xdd) && (sig_off + 15 <= msdu_length) && (f_flow != 0))
1789 sig_ts = get_signature_ts(m_ptr, sig_off);
1793 /* Set latency based on rx/tx and signature timestamp */
1795 if (sig_ts < s_time) {
1796 latency = (guint32)(s_time - sig_ts);
1798 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1799 /* we look for a large difference between l_time and s_time. */
1800 delta_b = sig_ts - s_time;
1801 if (delta_b > 0x10000000) {
1804 latency = (guint32)delta_b;
1809 * Fill up the per-packet header.
1811 * We include the length of the metadata headers in the packet lengths.
1813 phdr->len = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
1814 phdr->caplen = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
1816 phdr->ts.secs = (time_t)s_sec;
1817 phdr->ts.nsecs = (int)(s_usec * 1000);
1818 phdr->pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1820 phdr->rec_type = REC_TYPE_PACKET;
1821 phdr->presence_flags = WTAP_HAS_TS;
1823 /*etap_hdr.vw_ip_length = (guint16)ip_len;*/
1825 ws_buffer_assure_space(buf, phdr->caplen);
1826 data_ptr = ws_buffer_start_ptr(buf);
1829 * Generate and copy out the common metadata headers,
1830 * set the port type to 1 (Ethernet).
1832 * All values are copied out in little-endian byte order.
1834 phtoles(&data_ptr[bytes_written], 1);
1836 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN);
1838 phtoles(&data_ptr[bytes_written], msdu_length);
1840 phtolel(&data_ptr[bytes_written], flow_id);
1842 phtoles(&data_ptr[bytes_written], vc_id);
1844 phtoles(&data_ptr[bytes_written], flow_seq);
1846 if (!IS_TX && (sig_ts != 0)) {
1847 phtolel(&data_ptr[bytes_written], latency);
1849 phtolel(&data_ptr[bytes_written], 0);
1852 phtolel(&data_ptr[bytes_written], sig_ts);
1854 phtolell(&data_ptr[bytes_written], start_time) /* record start & end times of frame */
1856 phtolell(&data_ptr[bytes_written], end_time);
1858 phtolel(&data_ptr[bytes_written], d_time);
1862 * Generate and copy out the Ethernet metadata headers.
1864 * All values are copied out in little-endian byte order.
1866 phtoles(&data_ptr[bytes_written], EXT_ETHERNET_FIELDS_LEN);
1870 vw_flags |= VW_FLAGS_TXF;
1871 if (errors & vwr->FCS_ERROR)
1872 vw_flags |= VW_FLAGS_FCSERR;
1873 phtoles(&data_ptr[bytes_written], vw_flags);
1875 phtoles(&data_ptr[bytes_written], info);
1877 phtolel(&data_ptr[bytes_written], errors);
1879 phtolel(&data_ptr[bytes_written], l4id);
1883 phtolel(&data_ptr[bytes_written], 0);
1887 * Finally, copy the whole MAC frame to the packet buffer as-is.
1888 * This also does not include the last 4 bytes, as those don't
1889 * contain an FCS, they just contain junk.
1891 memcpy(&data_ptr[bytes_written], m_ptr, actual_octets);
1896 /*--------------------------------------------------------------------------------------*/
1897 /* utility to split up and decode a 16-byte message record */
1899 static int decode_msg(guint8 *rec, int *v_type, int *IS_TX)
1901 guint8 cmd; /* components of message */
1903 int v_size = 0; /* size of var-len message */
1904 /* assume it's zero */
1906 /* break up the message record into its pieces */
1907 cmd = rec[0]; /* command byte */
1908 wd2 = pntoh32(&rec[8]); /* first 32-bit quantity */
1909 wd3 = pntoh32(&rec[12]); /* second 32-bit quantity */
1911 /* now decode based on the command byte */
1916 v_size = (int)(wd2 & 0xffff);
1923 v_size = (int)(wd2 & 0xffff);
1930 *IS_TX = 2; /*NULL case*/
1931 v_size = (int)(wd2 & 0xffff);
1937 *IS_TX = 2; /*NULL case*/
1938 v_size = (int)(wd3 & 0xffff);
1944 *IS_TX = 2; /*NULL case*/
1952 /*---------------------------------------------------------------------------------------*/
1953 /* Utilities to extract and decode the PHY bit rate from 802.11 PLCP headers (OFDM/CCK). */
1954 /* They are passed a pointer to 4 or 6 consecutive bytes of PLCP header. */
1955 /* The integer returned by the get_xxx_rate() functions is in units of 0.5 Mb/s. */
1956 /* The string returned by the decode_xxx_rate() functions is 3 characters wide. */
1958 static guint8 get_ofdm_rate(const guint8 *plcp)
1960 /* extract the RATE field (LS nibble of first byte) then convert it to the MCS index used by the L1p fields */
1961 switch (plcp[0] & 0x0f) {
1962 case 0x0b: return 4;
1963 case 0x0f: return 5;
1964 case 0x0a: return 6;
1965 case 0x0e: return 7;
1966 case 0x09: return 8;
1967 case 0x0d: return 9;
1968 case 0x08: return 10;
1969 case 0x0c: return 11;
1974 static guint8 get_cck_rate(const guint8 *plcp)
1976 /* extract rate from the SIGNAL field then convert it to the MCS index used by the L1p fields */
1978 case 0x0a: return 0;
1979 case 0x14: return 1;
1980 case 0x37: return 2;
1981 case 0x6e: return 3;
1986 /*--------------------------------------------------------------------------------------*/
1987 /* utility to set up offsets and bitmasks for decoding the stats blocks */
1989 static void setup_defaults(vwr_t *vwr, guint16 fpga)
1994 vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
1996 vwr->VALID_OFF = vVW510021_W_VALID_OFF;
1997 vwr->MTYPE_OFF = vVW510021_W_MTYPE_OFF;
1998 vwr->VCID_OFF = vVW510021_W_VCID_OFF;
1999 vwr->FLOWSEQ_OFF = vVW510021_W_FLOWSEQ_OFF;
2000 vwr->FLOWID_OFF = vVW510021_W_FLOWID_OFF;
2002 /*vwr->OCTET_OFF = v22_W_OCTET_OFF;*/
2004 vwr->ERRORS_OFF = vVW510021_W_ERRORS_OFF;
2005 vwr->PATN_OFF = vVW510021_W_MATCH_OFF;
2006 vwr->RSSI_OFF = vVW510021_W_RSSI_TXPOWER_OFF;
2007 vwr->STARTT_OFF = vVW510021_W_STARTT_OFF;
2008 vwr->ENDT_OFF = vVW510021_W_ENDT_OFF;
2009 vwr->LATVAL_OFF = vVW510021_W_LATVAL_OFF;
2010 vwr->INFO_OFF = vVW510021_W_INFO_OFF;
2011 vwr->FPGA_VERSION_OFF = S2_W_FPGA_VERSION_OFF;
2012 vwr->HEADER_VERSION_OFF = vVW510021_W_HEADER_VERSION_OFF;
2013 vwr->OCTET_OFF = vVW510021_W_MSDU_LENGTH_OFF;
2014 vwr->L1P_1_OFF = vVW510021_W_L1P_1_OFF;
2015 vwr->L1P_2_OFF = vVW510021_W_L1P_2_OFF;
2016 vwr->L4ID_OFF = vVW510021_W_L4ID_OFF;
2017 vwr->IPLEN_OFF = vVW510021_W_IPLEN_OFF;
2018 vwr->PLCP_LENGTH_OFF = vVW510021_W_PLCP_LENGTH_OFF;
2020 vwr->MT_MASK = vVW510021_W_SEL_MASK;
2021 vwr->VCID_MASK = 0xffff;
2022 vwr->FLOW_VALID = vVW510021_W_FLOW_VALID;
2023 vwr->STATS_START_OFF = vVW510021_W_HEADER_LEN;
2024 vwr->FCS_ERROR = vVW510021_W_FCS_ERROR;
2025 vwr->CRYPTO_ERR = v22_W_CRYPTO_ERR;
2026 vwr->RETRY_ERR = v22_W_RETRY_ERR;
2028 /*vwr->STATS_START_OFF = 0;*/
2030 vwr->RXTX_OFF = vVW510021_W_RXTX_OFF;
2032 vwr->MT_10_HALF = 0;
2033 vwr->MT_10_FULL = 0;
2034 vwr->MT_100_HALF = 0;
2035 vwr->MT_100_FULL = 0;
2036 vwr->MT_1G_HALF = 0;
2037 vwr->MT_1G_FULL = 0;
2038 vwr->MT_CCKL = v22_W_MT_CCKL;
2039 vwr->MT_CCKS = v22_W_MT_CCKS;
2040 /*vwr->MT_OFDM = vVW510021_W_MT_OFDM;*/
2042 vwr->WEPTYPE = v22_W_WEPTYPE;
2043 vwr->TKIPTYPE = v22_W_TKIPTYPE;
2044 vwr->CCMPTYPE = v22_W_CCMPTYPE;
2046 vwr->FRAME_TYPE_OFF = vVW510021_W_FRAME_TYPE_OFF;
2047 vwr->IS_TCP = vVW510021_W_IS_TCP;
2048 vwr->IS_UDP = vVW510021_W_IS_UDP;
2049 vwr->IS_ICMP = vVW510021_W_IS_ICMP;
2050 vwr->IS_IGMP = vVW510021_W_IS_IGMP;
2051 vwr->IS_QOS = vVW510021_W_QOS_VALID;
2054 * The 12 is for 11 bytes of PLCP and 1 byte of pad
2057 vwr->MPDU_OFF = vVW510021_W_STATS_HEADER_LEN + 12;
2062 vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
2063 vwr->PLCP_LENGTH_OFF = 16;
2066 * The first 16 is from the 16 bytes of stats block that
2067 * precede the PLCP; the 16 is for 16 bytes of PLCP.
2069 vwr->MPDU_OFF = 16 + 16;
2073 case vVW510012_E_FPGA:
2074 vwr->STATS_LEN = v22_E_STATS_LEN;
2076 vwr->VALID_OFF = v22_E_VALID_OFF;
2077 vwr->MTYPE_OFF = v22_E_MTYPE_OFF;
2078 vwr->VCID_OFF = v22_E_VCID_OFF;
2079 vwr->FLOWSEQ_OFF = v22_E_FLOWSEQ_OFF;
2080 vwr->FLOWID_OFF = v22_E_FLOWID_OFF;
2081 vwr->OCTET_OFF = v22_E_OCTET_OFF;
2082 vwr->ERRORS_OFF = v22_E_ERRORS_OFF;
2083 vwr->PATN_OFF = v22_E_PATN_OFF;
2084 vwr->RSSI_OFF = v22_E_RSSI_OFF;
2085 vwr->STARTT_OFF = v22_E_STARTT_OFF;
2086 vwr->ENDT_OFF = v22_E_ENDT_OFF;
2087 vwr->LATVAL_OFF = v22_E_LATVAL_OFF;
2088 vwr->INFO_OFF = v22_E_INFO_OFF;
2089 vwr->L4ID_OFF = v22_E_L4ID_OFF;
2091 vwr->IS_RX = v22_E_IS_RX;
2092 vwr->MT_MASK = v22_E_MT_MASK;
2093 vwr->VCID_MASK = v22_E_VCID_MASK;
2094 vwr->FLOW_VALID = v22_E_FLOW_VALID;
2095 vwr->FCS_ERROR = v22_E_FCS_ERROR;
2097 vwr->RX_DECRYPTS = v22_E_RX_DECRYPTS;
2098 vwr->TX_DECRYPTS = v22_E_TX_DECRYPTS;
2099 vwr->FC_PROT_BIT = v22_E_FC_PROT_BIT;
2101 vwr->MT_10_HALF = v22_E_MT_10_HALF;
2102 vwr->MT_10_FULL = v22_E_MT_10_FULL;
2103 vwr->MT_100_HALF = v22_E_MT_100_HALF;
2104 vwr->MT_100_FULL = v22_E_MT_100_FULL;
2105 vwr->MT_1G_HALF = v22_E_MT_1G_HALF;
2106 vwr->MT_1G_FULL = v22_E_MT_1G_FULL;
2111 vwr->FRAME_TYPE_OFF = v22_E_FRAME_TYPE_OFF;
2112 vwr->IS_TCP = v22_E_IS_TCP;
2113 vwr->IS_UDP = v22_E_IS_UDP;
2114 vwr->IS_ICMP = v22_E_IS_ICMP;
2115 vwr->IS_IGMP = v22_E_IS_IGMP;
2116 vwr->IS_QOS = v22_E_IS_QOS;
2117 vwr->IS_VLAN = v22_E_IS_VLAN;
2123 vwr->STATS_LEN = v22_W_STATS_LEN;
2125 vwr->MTYPE_OFF = v22_W_MTYPE_OFF;
2126 vwr->VALID_OFF = v22_W_VALID_OFF;
2127 vwr->VCID_OFF = v22_W_VCID_OFF;
2128 vwr->FLOWSEQ_OFF = v22_W_FLOWSEQ_OFF;
2129 vwr->FLOWID_OFF = v22_W_FLOWID_OFF;
2130 vwr->OCTET_OFF = v22_W_OCTET_OFF;
2131 vwr->ERRORS_OFF = v22_W_ERRORS_OFF;
2132 vwr->PATN_OFF = v22_W_PATN_OFF;
2133 vwr->RSSI_OFF = v22_W_RSSI_OFF;
2134 vwr->STARTT_OFF = v22_W_STARTT_OFF;
2135 vwr->ENDT_OFF = v22_W_ENDT_OFF;
2136 vwr->LATVAL_OFF = v22_W_LATVAL_OFF;
2137 vwr->INFO_OFF = v22_W_INFO_OFF;
2138 vwr->L4ID_OFF = v22_W_L4ID_OFF;
2139 vwr->IPLEN_OFF = v22_W_IPLEN_OFF;
2140 vwr->PLCP_LENGTH_OFF = v22_W_PLCP_LENGTH_OFF;
2142 vwr->FCS_ERROR = v22_W_FCS_ERROR;
2143 vwr->CRYPTO_ERR = v22_W_CRYPTO_ERR;
2144 vwr->PAYCHK_ERR = v22_W_PAYCHK_ERR;
2145 vwr->RETRY_ERR = v22_W_RETRY_ERR;
2146 vwr->IS_RX = v22_W_IS_RX;
2147 vwr->MT_MASK = v22_W_MT_MASK;
2148 vwr->VCID_MASK = v22_W_VCID_MASK;
2149 vwr->FLOW_VALID = v22_W_FLOW_VALID;
2151 vwr->RX_DECRYPTS = v22_W_RX_DECRYPTS;
2152 vwr->TX_DECRYPTS = v22_W_TX_DECRYPTS;
2153 vwr->FC_PROT_BIT = v22_W_FC_PROT_BIT;
2155 vwr->MT_10_HALF = 0;
2156 vwr->MT_10_FULL = 0;
2157 vwr->MT_100_HALF = 0;
2158 vwr->MT_100_FULL = 0;
2159 vwr->MT_1G_HALF = 0;
2160 vwr->MT_1G_FULL = 0;
2161 vwr->MT_CCKL = v22_W_MT_CCKL;
2162 vwr->MT_CCKS = v22_W_MT_CCKS;
2163 vwr->MT_OFDM = v22_W_MT_OFDM;
2165 vwr->WEPTYPE = v22_W_WEPTYPE;
2166 vwr->TKIPTYPE = v22_W_TKIPTYPE;
2167 vwr->CCMPTYPE = v22_W_CCMPTYPE;
2169 vwr->FRAME_TYPE_OFF = v22_W_FRAME_TYPE_OFF;
2170 vwr->IS_TCP = v22_W_IS_TCP;
2171 vwr->IS_UDP = v22_W_IS_UDP;
2172 vwr->IS_ICMP = v22_W_IS_ICMP;
2173 vwr->IS_IGMP = v22_W_IS_IGMP;
2174 vwr->IS_QOS = v22_W_IS_QOS;
2178 /* Ethernet frames */
2179 case vVW510024_E_FPGA:
2180 vwr->STATS_LEN = vVW510024_E_STATS_LEN;
2182 vwr->VALID_OFF = vVW510024_E_VALID_OFF;
2183 vwr->VCID_OFF = vVW510024_E_VCID_OFF;
2184 vwr->FLOWSEQ_OFF = vVW510024_E_FLOWSEQ_OFF;
2185 vwr->FLOWID_OFF = vVW510024_E_FLOWID_OFF;
2186 vwr->OCTET_OFF = vVW510024_E_MSDU_LENGTH_OFF;
2187 vwr->ERRORS_OFF = vVW510024_E_ERRORS_OFF;
2188 vwr->PATN_OFF = vVW510024_E_MATCH_OFF;
2189 vwr->STARTT_OFF = vVW510024_E_STARTT_OFF;
2190 vwr->ENDT_OFF = vVW510024_E_ENDT_OFF;
2191 vwr->LATVAL_OFF = vVW510024_E_LATVAL_OFF;
2192 vwr->INFO_OFF = vVW510024_E_INFO_OFF;
2193 vwr->L4ID_OFF = vVW510024_E_L4ID_OFF;
2194 vwr->IPLEN_OFF = vVW510024_E_IPLEN_OFF;
2196 vwr->FPGA_VERSION_OFF = vVW510024_E_FPGA_VERSION_OFF;
2197 vwr->HEADER_VERSION_OFF = vVW510024_E_HEADER_VERSION_OFF;
2199 vwr->VCID_MASK = vVW510024_E_VCID_MASK;
2200 vwr->FLOW_VALID = vVW510024_E_FLOW_VALID;
2201 vwr->FCS_ERROR = v22_E_FCS_ERROR;
2203 vwr->FRAME_TYPE_OFF = vVW510024_E_FRAME_TYPE_OFF;
2204 vwr->IS_TCP = vVW510024_E_IS_TCP;
2205 vwr->IS_UDP = vVW510024_E_IS_UDP;
2206 vwr->IS_ICMP = vVW510024_E_IS_ICMP;
2207 vwr->IS_IGMP = vVW510024_E_IS_IGMP;
2208 vwr->IS_QOS = vVW510024_E_QOS_VALID;
2209 vwr->IS_VLAN = vVW510024_E_IS_VLAN;
2214 #define SIG_SCAN_RANGE 64 /* range of signature scanning region */
2216 /* Utility routine: check that signature is at specified location; scan for it if not. */
2217 /* If we can't find a signature at all, then simply return the originally supplied offset. */
2218 int find_signature(const guint8 *m_ptr, int rec_size, int pay_off, guint32 flow_id, guint8 flow_seq)
2220 int tgt; /* temps */
2223 /* initial check is very simple: look for a '0xdd' at the target location */
2224 if (m_ptr[pay_off] == 0xdd) /* if magic byte is present */
2225 return pay_off; /* got right offset, return it */
2227 /* Hmmm, signature magic byte is not where it is supposed to be; scan from start of */
2228 /* payload until maximum scan range exhausted to see if we can find it. */
2229 /* The scanning process consists of looking for a '0xdd', then checking for the correct */
2230 /* flow ID and sequence number at the appropriate offsets. */
2231 for (tgt = pay_off; tgt < (rec_size); tgt++) {
2232 if (m_ptr[tgt] == 0xdd) { /* found magic byte? check fields */
2233 if ((tgt + 15 < rec_size) && (m_ptr[tgt + 15] == 0xe2)) {
2234 if (m_ptr[tgt + 4] != flow_seq)
2237 fid = pletoh24(&m_ptr[tgt + 1]);
2244 else if (tgt + SIG_FSQ_OFF < rec_size)
2245 { /* out which one... */
2246 if (m_ptr[tgt + SIG_FSQ_OFF] != flow_seq) /* check sequence number */
2247 continue; /* if failed, keep scanning */
2249 fid = pletoh24(&m_ptr[tgt + SIG_FID_OFF]); /* assemble flow ID from signature */
2250 if (fid != flow_id) /* check flow ID against expected */
2251 continue; /* if failed, keep scanning */
2253 /* matched magic byte, sequence number, flow ID; found the signature */
2254 return (tgt); /* return offset of signature */
2259 /* failed to find the signature, return the original offset as default */
2263 /* utility routine: harvest the signature time stamp from the data frame */
2264 guint64 get_signature_ts(const guint8 *m_ptr,int sig_off)
2269 if (m_ptr[sig_off + 15] == 0xe2)
2274 sig_ts = pletoh32(&m_ptr[sig_off + ts_offset]);
2276 return (sig_ts & 0xffffffff);
2279 static float getRate( guint8 plcpType, guint8 mcsIndex, guint16 rflags, guint8 nss )
2281 /* Rate conversion data */
2282 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};
2284 static const int canonical_ndbps_20_ht[8] = {26, 52, 78, 104, 156, 208, 234, 260};
2285 static const int canonical_ndbps_40_ht[8] = {54, 108, 162, 216, 324, 432, 486, 540};
2287 static const int canonical_ndbps_20_vht[] = {26, 52, 78, 104, 156, 208, 234, 260, 312};
2288 static const int canonical_ndbps_40_vht[] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
2289 static const int canonical_ndbps_80_vht[] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
2291 float symbol_tx_time, bitrate = 0.0f;
2295 if (mcsIndex < G_N_ELEMENTS(canonical_rate_legacy))
2296 bitrate = canonical_rate_legacy[mcsIndex];
2298 else if (plcpType == 1 || plcpType == 2)
2302 if ( rflags & FLAGS_CHAN_SHORTGI)
2303 symbol_tx_time = 3.6f;
2305 symbol_tx_time = 4.0f;
2307 if ( rflags & FLAGS_CHAN_40MHZ )
2308 ndbps = canonical_ndbps_40_ht[mcsIndex & 0x07];
2310 ndbps = canonical_ndbps_20_ht[mcsIndex & 0x07];
2312 bitrate = ( ndbps * (((int)(mcsIndex >> 3) + 1) )) / symbol_tx_time;
2316 if ( rflags & FLAGS_CHAN_SHORTGI)
2317 symbol_tx_time = 3.6f;
2319 symbol_tx_time = 4.0f;
2321 /* Check for the out of range mcsIndex. Should never happen, but if mcs index is greater than 9 assume 9 is the value */
2322 if (mcsIndex > 9) mcsIndex = 9;
2323 if ( rflags & FLAGS_CHAN_40MHZ )
2324 bitrate = (canonical_ndbps_40_vht[ mcsIndex ] * nss) / symbol_tx_time;
2325 else if (rflags & FLAGS_CHAN_80MHZ )
2326 bitrate = (canonical_ndbps_80_vht[ mcsIndex ] * nss) / symbol_tx_time;
2329 if (mcsIndex == 9 && nss == 3)
2330 bitrate = 1040 / symbol_tx_time;
2331 else if (mcsIndex < 9)
2332 bitrate = (canonical_ndbps_20_vht[ mcsIndex ] * nss) / symbol_tx_time;
2340 vwr_process_rec_data(FILE_T fh, int rec_size,
2341 struct wtap_pkthdr *phdr, Buffer *buf, vwr_t *vwr,
2342 int IS_TX, int *err, gchar **err_info)
2344 guint8 rec[B_SIZE]; /* local buffer (holds input record) */
2346 /* Read over the entire record (frame + trailer) into a local buffer. */
2347 /* If we don't get it all, then declare an error, we can't process the frame. */
2348 if (!wtap_read_bytes(fh, rec, rec_size, err, err_info))
2351 /* now format up the frame data */
2352 switch (vwr->FPGA_VERSION)
2355 return vwr_read_s1_W_rec(vwr, phdr, buf, rec, rec_size, err, err_info);
2359 return vwr_read_s2_s3_W_rec(vwr, phdr, buf, rec, rec_size, IS_TX, err, err_info);
2361 case vVW510012_E_FPGA:
2362 case vVW510024_E_FPGA:
2363 return vwr_read_rec_data_ethernet(vwr, phdr, buf, rec, rec_size, IS_TX, err, err_info);
2366 g_assert_not_reached();
2372 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2377 * indent-tabs-mode: nil
2380 * vi: set shiftwidth=4 tabstop=8 expandtab:
2381 * :indentSize=4:tabSize=8:noTabs=true: