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
)
27 ssize_t ret
, hdrsize
= pcap_get_hdr_length(phdr
, type
);
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 fmemcpy(iov
[iov_slot
].iov_base
, &phdr
->raw
, hdrsize
);
38 iov
[iov_slot
].iov_len
= hdrsize
;
40 fmemcpy(iov
[iov_slot
].iov_base
+ iov
[iov_slot
].iov_len
, packet
, len
);
41 ret
= (iov
[iov_slot
].iov_len
+= len
);
47 static ssize_t
__pcap_sg_inter_iov_hdr_read(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
48 uint8_t *packet
, size_t len
, size_t hdrsize
)
54 offset
= iov
[iov_slot
].iov_len
- iov_off_rd
;
55 remainder
= hdrsize
- offset
;
59 bug_on(offset
+ remainder
!= hdrsize
);
61 fmemcpy(&phdr
->raw
, iov
[iov_slot
].iov_base
+ iov_off_rd
, offset
);
65 if (iov_slot
== array_size(iov
)) {
67 ret
= readv(fd
, iov
, array_size(iov
));
68 if (unlikely(ret
<= 0))
72 fmemcpy(&phdr
->raw
+ offset
, iov
[iov_slot
].iov_base
+ iov_off_rd
, remainder
);
73 iov_off_rd
+= remainder
;
78 static ssize_t
__pcap_sg_inter_iov_data_read(int fd
, uint8_t *packet
, size_t len
, size_t hdrlen
)
84 offset
= iov
[iov_slot
].iov_len
- iov_off_rd
;
85 remainder
= hdrlen
- offset
;
89 bug_on(offset
+ remainder
!= hdrlen
);
91 fmemcpy(packet
, iov
[iov_slot
].iov_base
+ iov_off_rd
, offset
);
95 if (iov_slot
== array_size(iov
)) {
97 ret
= readv(fd
, iov
, array_size(iov
));
98 if (unlikely(ret
<= 0))
102 fmemcpy(packet
+ offset
, iov
[iov_slot
].iov_base
+ iov_off_rd
, remainder
);
103 iov_off_rd
+= remainder
;
108 static ssize_t
pcap_sg_read(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
109 uint8_t *packet
, size_t len
)
112 size_t hdrsize
= pcap_get_hdr_length(phdr
, type
), hdrlen
;
114 if (likely(iov
[iov_slot
].iov_len
- iov_off_rd
>= hdrsize
)) {
115 fmemcpy(&phdr
->raw
, iov
[iov_slot
].iov_base
+ iov_off_rd
, hdrsize
);
116 iov_off_rd
+= hdrsize
;
118 ret
= __pcap_sg_inter_iov_hdr_read(fd
, phdr
, type
, packet
,
120 if (unlikely(ret
< 0))
124 hdrlen
= pcap_get_length(phdr
, type
);
125 if (unlikely(hdrlen
== 0 || hdrlen
> len
))
128 if (likely(iov
[iov_slot
].iov_len
- iov_off_rd
>= hdrlen
)) {
129 fmemcpy(packet
, iov
[iov_slot
].iov_base
+ iov_off_rd
, hdrlen
);
130 iov_off_rd
+= hdrlen
;
132 ret
= __pcap_sg_inter_iov_data_read(fd
, packet
, len
, hdrlen
);
133 if (unlikely(ret
< 0))
137 return hdrsize
+ hdrlen
;
140 static void pcap_sg_fsync(int fd
)
142 ssize_t ret
= writev(fd
, iov
, iov_slot
);
144 panic("Writev I/O error: %s!\n", strerror(errno
));
150 static int pcap_sg_prepare_access(int fd
, enum pcap_mode mode
, bool jumbo
)
156 len
= jumbo
? (PAGE_SIZE
* 16) /* 64k max */ :
157 (PAGE_SIZE
* 3) /* 12k max */;
159 for (i
= 0; i
< array_size(iov
); ++i
) {
160 iov
[i
].iov_base
= xzmalloc_aligned(len
, 64);
161 iov
[i
].iov_len
= len
;
166 if (mode
== PCAP_MODE_RD
) {
167 ret
= readv(fd
, iov
, array_size(iov
));
178 static void pcap_sg_prepare_close(int fd
, enum pcap_mode mode
)
182 for (i
= 0; i
< array_size(iov
); ++i
)
183 xfree(iov
[i
].iov_base
);
186 const struct pcap_file_ops pcap_sg_ops
= {
187 .pull_fhdr_pcap
= pcap_generic_pull_fhdr
,
188 .push_fhdr_pcap
= pcap_generic_push_fhdr
,
189 .prepare_access_pcap
= pcap_sg_prepare_access
,
190 .prepare_close_pcap
= pcap_sg_prepare_close
,
191 .read_pcap
= pcap_sg_read
,
192 .write_pcap
= pcap_sg_write
,
193 .fsync_pcap
= pcap_sg_fsync
,