2 * Copyright (C) 2009, 2010 Daniel Borkmann <daniel@netsniff-ng.org> and
3 * Emmanuel Roullit <emmanuel@netsniff-ng.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
32 #include <arpa/inet.h>
34 #include <sys/ioctl.h>
37 #include <linux/if_ether.h>
38 #include <linux/if_packet.h>
39 #include <linux/filter.h>
40 #include <linux/version.h>
52 #ifdef __HAVE_TX_RING__
53 static void set_packet_loss_discard(int sock
)
56 int foo
= 1; /* we discard wrong packets */
59 setsockopt(sock
, SOL_PACKET
, PACKET_LOSS
, (void *)&foo
,
62 err("setsockopt: cannot set packet loss");
69 * destroy_virt_tx_ring - Destroys virtual TX_RING buffer
73 void destroy_virt_tx_ring(int sock
, struct ring_buff
*rb
)
77 memset(&(rb
->layout
), 0, sizeof(rb
->layout
));
78 setsockopt(sock
, SOL_PACKET
, PACKET_TX_RING
, (void *)&(rb
->layout
),
82 munmap(rb
->buffer
, rb
->len
);
91 * create_virt_tx_ring - Creates virtual TX_RING buffer
95 void create_virt_tx_ring(int sock
, struct ring_buff
*rb
, char *ifname
,
104 nic_flags
= get_nic_flags(ifname
);
106 if ((nic_flags
& IFF_UP
) != IFF_UP
) {
107 warn("The interface %s is not up\n\n", ifname
);
111 if ((nic_flags
& IFF_RUNNING
) != IFF_RUNNING
) {
112 warn("The interface %s is not running\n\n", ifname
);
116 dev_speed
= get_device_bitrate_generic_fallback(ifname
);
117 memset(&(rb
->layout
), 0, sizeof(rb
->layout
));
119 set_packet_loss_discard(sock
);
121 /* max: getpagesize() << 11 for i386 */
122 rb
->layout
.tp_block_size
= getpagesize() << 2;
123 rb
->layout
.tp_frame_size
= TPACKET_ALIGNMENT
<< 7;
125 /* max: 15 for i386, old default: 1 << 13, now: approximated bandwidth size */
127 rb
->layout
.tp_block_nr
=
128 ((dev_speed
* 1024 * 1024) / rb
->layout
.tp_block_size
);
130 rb
->layout
.tp_block_nr
=
131 usize
/ (rb
->layout
.tp_block_size
/ 1024);
134 rb
->layout
.tp_frame_nr
=
135 rb
->layout
.tp_block_size
/ rb
->layout
.tp_frame_size
*
136 rb
->layout
.tp_block_nr
;
140 setsockopt(sock
, SOL_PACKET
, PACKET_TX_RING
, (void *)&(rb
->layout
),
143 if (errno
== ENOMEM
&& rb
->layout
.tp_block_nr
> 1) {
144 rb
->layout
.tp_block_nr
>>= 1;
145 rb
->layout
.tp_frame_nr
=
146 rb
->layout
.tp_block_size
/ rb
->layout
.tp_frame_size
*
147 rb
->layout
.tp_block_nr
;
153 err("setsockopt: creation of tx ring failed");
158 rb
->len
= rb
->layout
.tp_block_size
* rb
->layout
.tp_block_nr
;
160 info("%.2f MB allocated for transmit ring \n",
161 1.f
* rb
->len
/ (1024 * 1024));
162 info(" [ %d blocks, %d frames ] \n", rb
->layout
.tp_block_nr
,
163 rb
->layout
.tp_frame_nr
);
164 info(" [ %d frames per block ]\n",
165 rb
->layout
.tp_block_size
/ rb
->layout
.tp_frame_size
);
166 info(" [ framesize: %d bytes, blocksize: %d bytes ]\n\n",
167 rb
->layout
.tp_frame_size
, rb
->layout
.tp_block_size
);
171 * mmap_virt_tx_ring - Memory maps virtual TX_RING kernel buffer into userspace
172 * in order to avoid syscalls for transmitting packet buffers
176 void mmap_virt_tx_ring(int sock
, struct ring_buff
*rb
)
181 mmap(0, rb
->len
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, sock
, 0);
182 if (rb
->buffer
== MAP_FAILED
) {
183 err("mmap: cannot mmap the tx ring");
185 destroy_virt_tx_ring(sock
, rb
);
193 * bind_dev_to_tx_ring - Binds virtual TX_RING to network device
195 * @ifindex: device number
198 void bind_dev_to_tx_ring(int sock
, int ifindex
, struct ring_buff
*rb
)
204 memset(&(rb
->params
), 0, sizeof(rb
->params
));
206 rb
->params
.sll_family
= AF_PACKET
;
207 rb
->params
.sll_protocol
= htons(ETH_P_ALL
);
208 rb
->params
.sll_ifindex
= ifindex
;
209 rb
->params
.sll_hatype
= 0;
210 rb
->params
.sll_halen
= 0;
211 rb
->params
.sll_pkttype
= 0;
214 bind(sock
, (struct sockaddr
*)&(rb
->params
),
215 sizeof(struct sockaddr_ll
));
217 err("bind: cannot bind device");
223 void transmit_packets(struct system_data
*sd
, int sock
, struct ring_buff
*rb
)
225 struct frame_map
*fm
;
226 struct tpacket_hdr
*header
;
238 pfd
.events
= POLLOUT
;
240 info("Starting transmitting\n");
242 while (likely(!sigint
)) {
243 for (i
= 0; i
< rb
->layout
.tp_block_nr
; i
++) {
244 fm
= rb
->frames
[i
].iov_base
;
245 header
= (struct tpacket_hdr
*)&fm
->tp_h
;
247 (uint8_t *) ((uintptr_t) rb
->frames
[i
].iov_base
+
249 sizeof(struct sockaddr_ll
));
251 switch ((volatile uint32_t)header
->tp_status
) {
252 case TP_STATUS_AVAILABLE
:
254 pcap_fetch_next_packet(sd
->pcap_fd
,
258 /* If the fetch packet does not match the BPF, take the next one */
260 (&sd
->bpf
, buff
, header
->tp_len
)) {
265 /* Prints all packets which match the BFP as unknown */
266 if (pkt_len
!= 0 && sd
->print_pkt
)
267 sd
->print_pkt(buff
, header
, 5);
269 /* No packets to replay or error, time to exit */
273 /* Mark packet as ready to send */
274 header
->tp_status
= TP_STATUS_SEND_REQUEST
;
277 case TP_STATUS_WRONG_FORMAT
:
278 warn("An error during transfer!\n");
289 ret
= send(sock
, NULL
, 0, 0);
292 err("Cannot flush tx_ring with send");
295 /* Now we wait that the kernel place all packet on the medium */
296 ret
= poll(&pfd
, 1, sd
->blocking_mode
);
299 err("An error occured while polling on %s\n", sd
->dev
);
308 * XXX: do the same stuff but only with sendmsg or similar
311 void bind_dev_to_tx_ring(int sock
, int ifindex
, struct ring_buff
*rb
)
316 void mmap_virt_tx_ring(int sock
, struct ring_buff
*rb
)
321 void create_virt_tx_ring(int sock
, struct ring_buff
*rb
, char *ifname
,
327 void destroy_virt_tx_ring(int sock
, struct ring_buff
*rb
)
332 int flush_virt_tx_ring(int sock
, struct ring_buff
*rb
)
337 void transmit_packets(struct system_data
*sd
, int sock
, struct ring_buff
*rb
)
341 info("--- Transmitting ---\n\n");
345 warn("The --replay functionality needs a kernel >= 2.6.31 \n\n");
347 #endif /* __HAVE_TX_RING__ */