VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/Pcap.cpp@ 46757

Last change on this file since 46757 was 38549, checked in by vboxsync, 13 years ago

GSO: UDP fragmentation offloading (#5846)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: Pcap.cpp 38549 2011-08-26 13:26:07Z vboxsync $ */
2/** @file
3 * Helpers for writing libpcap files.
4 */
5
6/*
7 * Copyright (C) 2006-2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include "Pcap.h"
22
23#include <iprt/file.h>
24#include <iprt/stream.h>
25#include <iprt/time.h>
26#include <iprt/err.h>
27#include <VBox/vmm/pdmnetinline.h>
28
29
30/*******************************************************************************
31* Structures and Typedefs *
32*******************************************************************************/
33
34/* "libpcap" magic */
35#define PCAP_MAGIC 0xa1b2c3d4
36
37/* "libpcap" file header (minus magic number). */
38struct pcap_hdr
39{
40 uint16_t version_major; /* major version number = 2 */
41 uint16_t version_minor; /* minor version number = 4 */
42 int32_t thiszone; /* GMT to local correction = 0 */
43 uint32_t sigfigs; /* accuracy of timestamps = 0 */
44 uint32_t snaplen; /* max length of captured packets, in octets = 0xffff */
45 uint32_t network; /* data link type = 01 */
46};
47
48/* "libpcap" record header. */
49struct pcaprec_hdr
50{
51 uint32_t ts_sec; /* timestamp seconds */
52 uint32_t ts_usec; /* timestamp microseconds */
53 uint32_t incl_len; /* number of octets of packet saved in file */
54 uint32_t orig_len; /* actual length of packet */
55};
56
57struct pcaprec_hdr_init
58{
59 uint32_t u32Magic;
60 struct pcap_hdr pcap;
61};
62
63
64/*******************************************************************************
65* Global Variables *
66*******************************************************************************/
67static pcaprec_hdr_init const s_Hdr =
68{
69 PCAP_MAGIC,
70 { 2, 4, 0, 0, 0xffff, 1 },
71};
72
73static const char s_szDummyData[] = { 0, 0, 0, 0 };
74
75/**
76 * Internal helper.
77 */
78static void pcapCalcHeader(struct pcaprec_hdr *pHdr, uint64_t StartNanoTS, size_t cbFrame, size_t cbMax)
79{
80 uint64_t u64TS = RTTimeNanoTS() - StartNanoTS;
81 pHdr->ts_sec = (uint32_t)(u64TS / 1000000000);
82 pHdr->ts_usec = (uint32_t)((u64TS / 1000) % 1000000);
83 pHdr->incl_len = (uint32_t)RT_MIN(cbFrame, cbMax);
84 pHdr->orig_len = (uint32_t)cbFrame;
85}
86
87
88/**
89 * Internal helper.
90 */
91static void pcapUpdateHeader(struct pcaprec_hdr *pHdr, size_t cbFrame, size_t cbMax)
92{
93 pHdr->incl_len = (uint32_t)RT_MIN(cbFrame, cbMax);
94 pHdr->orig_len = (uint32_t)cbFrame;
95}
96
97
98/**
99 * Writes the stream header.
100 *
101 * @returns IPRT status code, @see RTStrmWrite.
102 *
103 * @param pStream The stream handle.
104 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
105 */
106int PcapStreamHdr(PRTSTREAM pStream, uint64_t StartNanoTS)
107{
108 int rc1 = RTStrmWrite(pStream, &s_Hdr, sizeof(s_Hdr));
109 int rc2 = PcapStreamFrame(pStream, StartNanoTS, s_szDummyData, 60, sizeof(s_szDummyData));
110 return RT_SUCCESS(rc1) ? rc2 : rc1;
111}
112
113
114/**
115 * Writes a frame to a stream.
116 *
117 * @returns IPRT status code, @see RTStrmWrite.
118 *
119 * @param pStream The stream handle.
120 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
121 * @param pvFrame The start of the frame.
122 * @param cbFrame The size of the frame.
123 * @param cbMax The max number of bytes to include in the file.
124 */
125int PcapStreamFrame(PRTSTREAM pStream, uint64_t StartNanoTS, const void *pvFrame, size_t cbFrame, size_t cbMax)
126{
127 struct pcaprec_hdr Hdr;
128 pcapCalcHeader(&Hdr, StartNanoTS, cbFrame, cbMax);
129 int rc1 = RTStrmWrite(pStream, &Hdr, sizeof(Hdr));
130 int rc2 = RTStrmWrite(pStream, pvFrame, Hdr.incl_len);
131 return RT_SUCCESS(rc1) ? rc2 : rc1;
132}
133
134
135/**
136 * Writes a GSO frame to a stream.
137 *
138 * @returns IPRT status code, @see RTStrmWrite.
139 *
140 * @param pStream The stream handle.
141 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
142 * @param pGso Pointer to the GSO context.
143 * @param pvFrame The start of the GSO frame.
144 * @param cbFrame The size of the GSO frame.
145 * @param cbSegMax The max number of bytes to include in the file for
146 * each segment.
147 */
148int PcapStreamGsoFrame(PRTSTREAM pStream, uint64_t StartNanoTS, PCPDMNETWORKGSO pGso,
149 const void *pvFrame, size_t cbFrame, size_t cbSegMax)
150{
151 struct pcaprec_hdr Hdr;
152 pcapCalcHeader(&Hdr, StartNanoTS, 0, 0);
153
154 uint8_t const *pbFrame = (uint8_t const *)pvFrame;
155 uint8_t abHdrs[256];
156 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame);
157 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
158 {
159 uint32_t cbSegPayload, cbHdrs;
160 uint32_t offSegPayload = PDMNetGsoCarveSegment(pGso, pbFrame, cbFrame, iSeg, cSegs, abHdrs, &cbHdrs, &cbSegPayload);
161
162 pcapUpdateHeader(&Hdr, cbHdrs + cbSegPayload, cbSegMax);
163 int rc = RTStrmWrite(pStream, &Hdr, sizeof(Hdr));
164 if (RT_FAILURE(rc))
165 return rc;
166
167 rc = RTStrmWrite(pStream, abHdrs, RT_MIN(Hdr.incl_len, cbHdrs));
168 if (RT_SUCCESS(rc) && Hdr.incl_len > cbHdrs)
169 rc = RTStrmWrite(pStream, pbFrame + offSegPayload, Hdr.incl_len - cbHdrs);
170 if (RT_FAILURE(rc))
171 return rc;
172 }
173
174 return VINF_SUCCESS;
175}
176
177
178/**
179 * Writes the file header.
180 *
181 * @returns IPRT status code, @see RTFileWrite.
182 *
183 * @param File The file handle.
184 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
185 */
186int PcapFileHdr(RTFILE File, uint64_t StartNanoTS)
187{
188 int rc1 = RTFileWrite(File, &s_Hdr, sizeof(s_Hdr), NULL);
189 int rc2 = PcapFileFrame(File, StartNanoTS, s_szDummyData, 60, sizeof(s_szDummyData));
190 return RT_SUCCESS(rc1) ? rc2 : rc1;
191}
192
193
194/**
195 * Writes a frame to a file.
196 *
197 * @returns IPRT status code, @see RTFileWrite.
198 *
199 * @param File The file handle.
200 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
201 * @param pvFrame The start of the frame.
202 * @param cbFrame The size of the frame.
203 * @param cbMax The max number of bytes to include in the file.
204 */
205int PcapFileFrame(RTFILE File, uint64_t StartNanoTS, const void *pvFrame, size_t cbFrame, size_t cbMax)
206{
207 struct pcaprec_hdr Hdr;
208 pcapCalcHeader(&Hdr, StartNanoTS, cbFrame, cbMax);
209 int rc1 = RTFileWrite(File, &Hdr, sizeof(Hdr), NULL);
210 int rc2 = RTFileWrite(File, pvFrame, Hdr.incl_len, NULL);
211 return RT_SUCCESS(rc1) ? rc2 : rc1;
212}
213
214
215/**
216 * Writes a GSO frame to a file.
217 *
218 * @returns IPRT status code, @see RTFileWrite.
219 *
220 * @param File The file handle.
221 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
222 * @param pGso Pointer to the GSO context.
223 * @param pvFrame The start of the GSO frame.
224 * @param cbFrame The size of the GSO frame.
225 * @param cbSegMax The max number of bytes to include in the file for
226 * each segment.
227 */
228int PcapFileGsoFrame(RTFILE File, uint64_t StartNanoTS, PCPDMNETWORKGSO pGso,
229 const void *pvFrame, size_t cbFrame, size_t cbSegMax)
230{
231 struct pcaprec_hdr Hdr;
232 pcapCalcHeader(&Hdr, StartNanoTS, 0, 0);
233
234 uint8_t const *pbFrame = (uint8_t const *)pvFrame;
235 uint8_t abHdrs[256];
236 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame);
237 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
238 {
239 uint32_t cbSegPayload, cbHdrs;
240 uint32_t offSegPayload = PDMNetGsoCarveSegment(pGso, pbFrame, cbFrame, iSeg, cSegs, abHdrs, &cbHdrs, &cbSegPayload);
241
242 pcapUpdateHeader(&Hdr, cbHdrs + cbSegPayload, cbSegMax);
243 int rc = RTFileWrite(File, &Hdr, sizeof(Hdr), NULL);
244 if (RT_FAILURE(rc))
245 return rc;
246
247 rc = RTFileWrite(File, abHdrs, RT_MIN(Hdr.incl_len, cbHdrs), NULL);
248 if (RT_SUCCESS(rc) && Hdr.incl_len > cbHdrs)
249 rc = RTFileWrite(File, pbFrame + offSegPayload, Hdr.incl_len - cbHdrs, NULL);
250 if (RT_FAILURE(rc))
251 return rc;
252 }
253
254 return VINF_SUCCESS;
255}
256
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette