1 /* For terms of usage/redistribution/modification see the LICENSE file */
2 /* For authors and contributors see the AUTHORS file */
4 #include "iptraf-ng-compat.h"
9 struct capt_data_mmap_v3
{
13 struct tpacket_block_desc
**pbds
;
14 struct tpacket_block_desc
*pbd
;
15 struct tpacket3_hdr
*ppd
;
16 unsigned int curblock
;
17 unsigned int lastblock
;
19 uint32_t num_pkts
; /* only for debug */
20 uint32_t cur_pkt
; /* only for debug */
23 #define BLOCKS 256 /* 256 blocks / 512 frames in each block:
24 * this gets room for 128k packets, which
25 * "should be enough for everybody" ;-) */
27 #define FRAMES_PER_BLOCK 512 /* keep it as power-of-two (dramaticly lowers
30 #define FRAMES (BLOCKS * FRAMES_PER_BLOCK) /* frames over all blocks */
32 #define FRAME_SIZE TPACKET_ALIGN(MAX_PACKET_SIZE + TPACKET_HDRLEN)
34 static struct tpacket_block_desc
*capt_mmap_find_filled_block(struct capt_data_mmap_v3
*data
)
36 for (unsigned int i
= data
->lastblock
; i
< data
->lastblock
+ BLOCKS
; i
++) {
37 unsigned int block
= i
>= BLOCKS
? i
- BLOCKS
: i
;
39 if (data
->pbds
[block
]->hdr
.bh1
.block_status
& TP_STATUS_USER
) {
40 data
->curblock
= block
;
41 return data
->pbds
[block
];
47 static unsigned int capt_have_packet_mmap_v3(struct capt
*capt
)
49 struct capt_data_mmap_v3
*data
= capt
->priv
;
51 if (data
->pbd
!= NULL
)
54 data
->pbd
= capt_mmap_find_filled_block(data
);
55 if (data
->pbd
!= NULL
)
61 static int capt_get_packet_mmap_v3(struct capt
*capt
, struct pkt_hdr
*pkt
)
63 struct capt_data_mmap_v3
*data
= capt
->priv
;
65 if (data
->pbd
== NULL
)
66 data
->pbd
= capt_mmap_find_filled_block(data
);
68 if (data
->pbd
== NULL
)
69 return 0; /* no packet ready */
71 if (data
->ppd
== NULL
) {
72 data
->ppd
= (struct tpacket3_hdr
*) ((uint8_t *)data
->pbd
+ data
->pbd
->hdr
.bh1
.offset_to_first_pkt
);
73 data
->num_pkts
= data
->pbd
->hdr
.bh1
.num_pkts
;
76 /* here should be at least one packet ready */
77 pkt
->pkt_buf
= (char *)data
->ppd
+ data
->ppd
->tp_mac
;
78 pkt
->pkt_payload
= NULL
;
79 pkt
->pkt_len
= data
->ppd
->tp_len
;
80 pkt
->from
= (struct sockaddr_ll
*)((uint8_t *)data
->ppd
+ data
->hdrlen
);
81 pkt
->pkt_protocol
= ntohs(pkt
->from
->sll_protocol
);
86 static int capt_put_packet_mmap_v3(struct capt
*capt
, struct pkt_hdr
*pkt __unused
)
88 struct capt_data_mmap_v3
*data
= capt
->priv
;
90 if (data
->ppd
->tp_next_offset
!= 0) {
91 data
->ppd
= (struct tpacket3_hdr
*)((uint8_t *)data
->ppd
+ data
->ppd
->tp_next_offset
);
97 data
->pbd
->hdr
.bh1
.block_status
= TP_STATUS_KERNEL
;
99 data
->lastblock
= data
->curblock
;
105 static void capt_cleanup_mmap_v3(struct capt
*capt
)
107 struct capt_data_mmap_v3
*data
= capt
->priv
;
111 munlock(data
->mmap
, data
->mmap_size
);
112 munmap(data
->mmap
, data
->mmap_size
);
114 memset(data
, 0, sizeof(*data
));
120 int capt_setup_mmap_v3(struct capt
*capt
)
122 int version
= TPACKET_V3
;
123 if (setsockopt(capt
->fd
, SOL_PACKET
, PACKET_VERSION
, &version
, sizeof(version
)) != 0)
126 int hdrlen
= version
;
127 socklen_t socklen
= sizeof(hdrlen
);
128 if (getsockopt(capt
->fd
, SOL_PACKET
, PACKET_HDRLEN
, &hdrlen
, &socklen
) != 0)
131 struct tpacket_req3 req
;
133 req
.tp_block_nr
= BLOCKS
;
134 req
.tp_frame_nr
= FRAMES
;
135 req
.tp_frame_size
= FRAME_SIZE
;
136 req
.tp_block_size
= FRAMES_PER_BLOCK
* req
.tp_frame_size
;
138 req
.tp_retire_blk_tov
= 20; /* block retire timeout in msec */
139 req
.tp_sizeof_priv
= 0;
140 // req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
142 if(setsockopt(capt
->fd
, SOL_PACKET
, PACKET_RX_RING
, &req
, sizeof(req
)) != 0)
145 size_t size
= req
.tp_block_size
* req
.tp_block_nr
;
146 void *map
= mmap(NULL
, size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, capt
->fd
, 0);
147 if (map
== MAP_FAILED
)
150 if (mlock(map
, size
) != 0) {
155 struct capt_data_mmap_v3
*data
= xmallocz(sizeof(struct capt_data_mmap_v3
));
157 data
->hdrlen
= hdrlen
;
159 data
->mmap_size
= size
;
161 data
->pbds
= xmallocz(BLOCKS
* sizeof(*data
->pbd
));
162 for (int i
= 0; i
< BLOCKS
; i
++) {
163 data
->pbds
[i
] = map
+ i
* req
.tp_block_size
;
167 capt
->have_packet
= capt_have_packet_mmap_v3
;
168 capt
->get_packet
= capt_get_packet_mmap_v3
;
169 capt
->put_packet
= capt_put_packet_mmap_v3
;
170 capt
->cleanup
= capt_cleanup_mmap_v3
;
172 return 0; /* All O.K. */