20 #include <arpa/inet.h> 26 #include <sys/socket.h> 28 #include <linux/if_packet.h> 29 #include <linux/if_ether.h> 33 # define likely(x) __builtin_expect(!!(x), 1) 36 # define unlikely(x) __builtin_expect(!!(x), 0) 62 int err, fd, v = TPACKET_V3;
64 unsigned int blocksiz = 1 << 22, framesiz = 1 << 11;
65 unsigned int blocknum = 64;
67 fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
73 err = setsockopt(fd, SOL_PACKET, PACKET_VERSION, &v,
sizeof(v));
79 memset(&ring->
req, 0,
sizeof(ring->
req));
80 ring->
req.tp_block_size = blocksiz;
81 ring->
req.tp_frame_size = framesiz;
82 ring->
req.tp_block_nr = blocknum;
83 ring->
req.tp_frame_nr = (blocksiz * blocknum) / framesiz;
84 ring->
req.tp_retire_blk_tov = 60;
85 ring->
req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
87 err = setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &ring->
req,
94 ring->
map = (uint8_t*)mmap(NULL, ring->
req.tp_block_size * ring->
req.tp_block_nr,
95 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0);
96 if (ring->
map == MAP_FAILED) {
101 ring->
rd = (iovec*)malloc(ring->
req.tp_block_nr *
sizeof(*ring->
rd));
103 for (i = 0; i < ring->
req.tp_block_nr; ++i) {
104 ring->
rd[i].iov_base = ring->
map + (i * ring->
req.tp_block_size);
105 ring->
rd[i].iov_len = ring->
req.tp_block_size;
108 memset(&ll, 0,
sizeof(ll));
109 ll.sll_family = PF_PACKET;
110 ll.sll_protocol = htons(ETH_P_ALL);
111 ll.sll_ifindex = if_nametoindex(netdev);
116 err = bind(fd, (sockaddr *) &ll,
sizeof(ll));
127 ethhdr *eth = (ethhdr *) ((uint8_t *) ppd + ppd->tp_mac);
128 iphdr *ip = (iphdr *) ((uint8_t *) eth + ETH_HLEN);
131 if (eth->h_proto == htons(ETH_P_IP)) {
133 char sbuff[NI_MAXHOST], dbuff[NI_MAXHOST];
135 memset(&ss, 0,
sizeof(ss));
136 ss.sin_family = PF_INET;
137 ss.sin_addr.s_addr = ip->saddr;
138 getnameinfo((sockaddr *) &ss,
sizeof(ss),
139 sbuff,
sizeof(sbuff), NULL, 0, NI_NUMERICHOST);
141 memset(&sd, 0,
sizeof(sd));
142 sd.sin_family = PF_INET;
143 sd.sin_addr.s_addr = ip->daddr;
144 getnameinfo((sockaddr *) &sd,
sizeof(sd),
145 dbuff,
sizeof(dbuff), NULL, 0, NI_NUMERICHOST);
161 int num_pkts = pbd->
h1.num_pkts, i;
162 unsigned long bytes = 0;
165 ppd = (tpacket3_hdr *) ((uint8_t *) pbd +
166 pbd->
h1.offset_to_first_pkt);
167 for (i = 0; i < num_pkts; ++i) {
168 bytes += ppd->tp_snaplen;
171 ppd = (tpacket3_hdr *) ((uint8_t *) ppd +
172 ppd->tp_next_offset);
181 pbd->
h1.block_status = TP_STATUS_KERNEL;
186 munmap(ring->
map, ring->
req.tp_block_size * ring->
req.tp_block_nr);
191 int main(
int argc,
char **argp)
197 unsigned int block_num = 0, blocks = 64;
199 tpacket_stats_v3 stats;
202 fprintf(stderr,
"Usage: %s INTERFACE\n", argp[0]);
208 printf(
"setting up socket\n");
209 memset(&ring, 0,
sizeof(ring));
213 memset(&pfd, 0,
sizeof(pfd));
215 pfd.events = POLLIN | POLLERR;
218 printf(
"waiting for packets\n");
223 if ((pbd->
h1.block_status & TP_STATUS_USER) == 0) {
230 block_num = (block_num + 1) % blocks;
235 err = getsockopt(fd, SOL_PACKET, PACKET_STATISTICS, &stats, &len);
237 perror(
"getsockopt");
242 printf(
"\nReceived %u packets, %lu bytes, %u dropped, freeze_q_cnt: %u\n",
244 stats.tp_freeze_q_cnt);
static unsigned long packets_total
static unsigned long bytes_total
static sig_atomic_t sigint
static int setup_socket(ring *ring, char *netdev)
static void display(tpacket3_hdr *ppd)
int main(int argc, char **argp)
static void sighandler(int)
static void walk_block(block_desc *pbd, const int)
static void teardown_socket(ring *ring, int fd)
static void flush_block(block_desc *pbd)