2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 - 2013 Daniel Borkmann.
5 * Subject to the GPL, version 2.
21 static struct iovec iov
[1024] __cacheline_aligned
;
22 static off_t iov_off_rd
= 0, iov_slot
= 0;
24 static ssize_t
pcap_sg_write(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
25 const uint8_t *packet
, size_t len
)
29 if (unlikely(iov_slot
== array_size(iov
))) {
30 ret
= writev(fd
, iov
, array_size(iov
));
32 panic("Writev I/O error: %s!\n", strerror(errno
));
37 iov
[iov_slot
].iov_len
= 0;
39 #define PCAP_HDR_WRITE(__member__) do { \
40 fmemcpy(iov[iov_slot].iov_base, &phdr->__member__, \
41 sizeof(phdr->__member__)); \
42 iov[iov_slot].iov_len += sizeof(phdr->__member__); \
44 #define CASE_HDR_WRITE(what, member) \
46 PCAP_HDR_WRITE(member); \
48 CASE_HDR_WRITE(DEFAULT
, ppo
);
49 CASE_HDR_WRITE(NSEC
, ppn
);
50 CASE_HDR_WRITE(KUZNETZOV
, ppk
);
51 CASE_HDR_WRITE(BORKMANN
, ppb
);
56 fmemcpy(iov
[iov_slot
].iov_base
+ iov
[iov_slot
].iov_len
, packet
, len
);
57 ret
= (iov
[iov_slot
].iov_len
+= len
);
63 static ssize_t
__pcap_sg_inter_iov_hdr_read(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
64 uint8_t *packet
, size_t len
, size_t hdrsize
)
70 offset
= iov
[iov_slot
].iov_len
- iov_off_rd
;
71 remainder
= hdrsize
- offset
;
75 bug_on(offset
+ remainder
!= hdrsize
);
78 #define CASE_HDR_PREAD(what, __member__) \
80 fmemcpy(&phdr->__member__, \
81 iov[iov_slot].iov_base + iov_off_rd, offset); \
83 CASE_HDR_PREAD(DEFAULT
, ppo
);
84 CASE_HDR_PREAD(NSEC
, ppn
);
85 CASE_HDR_PREAD(KUZNETZOV
, ppk
);
86 CASE_HDR_PREAD(BORKMANN
, ppb
);
94 if (iov_slot
== array_size(iov
)) {
96 ret
= readv(fd
, iov
, array_size(iov
));
97 if (unlikely(ret
<= 0))
102 #define CASE_HDR_RREAD(what, __member__) \
104 fmemcpy(&phdr->__member__ + offset, \
105 iov[iov_slot].iov_base + iov_off_rd, remainder); \
107 CASE_HDR_RREAD(DEFAULT
, ppo
);
108 CASE_HDR_RREAD(NSEC
, ppn
);
109 CASE_HDR_RREAD(KUZNETZOV
, ppk
);
110 CASE_HDR_RREAD(BORKMANN
, ppb
);
115 iov_off_rd
+= remainder
;
120 static ssize_t
__pcap_sg_inter_iov_data_read(int fd
, uint8_t *packet
, size_t len
, size_t hdrlen
)
126 offset
= iov
[iov_slot
].iov_len
- iov_off_rd
;
127 remainder
= hdrlen
- offset
;
131 bug_on(offset
+ remainder
!= hdrlen
);
133 fmemcpy(packet
, iov
[iov_slot
].iov_base
+ iov_off_rd
, offset
);
137 if (iov_slot
== array_size(iov
)) {
139 ret
= readv(fd
, iov
, array_size(iov
));
140 if (unlikely(ret
<= 0))
144 fmemcpy(packet
+ offset
, iov
[iov_slot
].iov_base
+ iov_off_rd
, remainder
);
145 iov_off_rd
+= remainder
;
150 static ssize_t
pcap_sg_read(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
151 uint8_t *packet
, size_t len
)
154 size_t hdrsize
= pcap_get_hdr_length(phdr
, type
), hdrlen
;
156 if (likely(iov
[iov_slot
].iov_len
- iov_off_rd
>= hdrsize
)) {
158 #define CASE_HDR_READ(what, __member__) \
160 fmemcpy(&phdr->__member__, \
161 iov[iov_slot].iov_base + iov_off_rd, hdrsize); \
163 CASE_HDR_READ(DEFAULT
, ppo
);
164 CASE_HDR_READ(NSEC
, ppn
);
165 CASE_HDR_READ(KUZNETZOV
, ppk
);
166 CASE_HDR_READ(BORKMANN
, ppb
);
171 iov_off_rd
+= hdrsize
;
173 ret
= __pcap_sg_inter_iov_hdr_read(fd
, phdr
, type
, packet
,
175 if (unlikely(ret
< 0))
179 hdrlen
= pcap_get_length(phdr
, type
);
180 if (unlikely(hdrlen
== 0 || hdrlen
> len
))
183 if (likely(iov
[iov_slot
].iov_len
- iov_off_rd
>= hdrlen
)) {
184 fmemcpy(packet
, iov
[iov_slot
].iov_base
+ iov_off_rd
, hdrlen
);
185 iov_off_rd
+= hdrlen
;
187 ret
= __pcap_sg_inter_iov_data_read(fd
, packet
, len
, hdrlen
);
188 if (unlikely(ret
< 0))
192 return hdrsize
+ hdrlen
;
195 static void pcap_sg_fsync(int fd
)
197 ssize_t ret
= writev(fd
, iov
, iov_slot
);
199 panic("Writev I/O error: %s!\n", strerror(errno
));
205 static int pcap_sg_prepare_access(int fd
, enum pcap_mode mode
, bool jumbo
)
211 len
= jumbo
? (PAGE_SIZE
* 16) /* 64k max */ :
212 (PAGE_SIZE
* 3) /* 12k max */;
214 for (i
= 0; i
< array_size(iov
); ++i
) {
215 iov
[i
].iov_base
= xzmalloc_aligned(len
, 64);
216 iov
[i
].iov_len
= len
;
221 if (mode
== PCAP_MODE_RD
) {
222 ret
= readv(fd
, iov
, array_size(iov
));
233 static void pcap_sg_prepare_close(int fd
, enum pcap_mode mode
)
237 for (i
= 0; i
< array_size(iov
); ++i
)
238 xfree(iov
[i
].iov_base
);
241 const struct pcap_file_ops pcap_sg_ops
= {
242 .pull_fhdr_pcap
= pcap_generic_pull_fhdr
,
243 .push_fhdr_pcap
= pcap_generic_push_fhdr
,
244 .prepare_access_pcap
= pcap_sg_prepare_access
,
245 .prepare_close_pcap
= pcap_sg_prepare_close
,
246 .read_pcap
= pcap_sg_read
,
247 .write_pcap
= pcap_sg_write
,
248 .fsync_pcap
= pcap_sg_fsync
,