c++ - PACKET_TX_RING only sending out first packet, then not doing anything anymore -


i have following code:

#ifndef rawsocket_h #define rawsocket_h  #include <stdio.h>  #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdint.h> #include <unistd.h>  #include <assert.h> #include <errno.h> #include <fcntl.h> #include <poll.h>  #include <arpa/inet.h> #include <netinet/if_ether.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/stat.h>  #include <linux/if.h> #include <linux/if_packet.h>  #include "ippacket.h"  #define conf_ring_frames        128  /// initialize packet socket ring buffer //  @param ringtype 1 of packet_rx_ring or packet_tx_ring static inline char * init_packetsock_ring(int fd, int ringtype) {   tpacket_req tp;   char *ring;    // tell kernel export data through mmap()ped ring   tp.tp_block_size = 1024 * 8;   tp.tp_block_nr = 1024;   tp.tp_frame_size = 1024 * 8;   tp.tp_frame_nr = 1024;   setsockopt(fd, sol_packet, ringtype, (void*) &tp, sizeof(tp));    int val = tpacket_v1;   setsockopt(fd, sol_packet, packet_version, &val, sizeof(val));    // open ring   ring = (char*)mmap(0, tp.tp_block_size * tp.tp_block_nr,                prot_read | prot_write, map_shared, fd, 0);    if (!ring)     return null;    return ring; }  /// transmit packet using packet ring //  note: high rate processing try batch system calls, //        writing multiple packets ring before calling send() // //  @param pkt packet network layer (e.g., ip) //  @return 0 on success, -1 on failure static inline int process_tx(int fd, char *ring, const char *pkt, int pktlen, sockaddr_ll *txring_daddr) {   static int ring_offset = 0;    struct tpacket_hdr *header;   struct pollfd pollset;   char *off;   int ret;    // fetch frame   // in packet_rx_ring case, define frames page long,   // including header. explains use of getpagesize().   header = (tpacket_hdr*)(void *) ring + (ring_offset * 1024);    while (header->tp_status != tp_status_available) {      // if none available: wait on more data     pollset.fd = fd;     pollset.events = pollout;     pollset.revents = 0;     ret = poll(&pollset, 1, 1000 /* don't hang */);     if (ret < 0) {       if (errno != eintr) {         perror("poll");         return -1;       }       return 0;     }      ring_offset++;     if(ring_offset >= 1024 * 8) ring_offset = 0;     header = (tpacket_hdr*)(void *) ring + (ring_offset * 1024);   }    // fill data   off = (char*)(((char*) header) + (tpacket_hdrlen - sizeof(struct sockaddr_ll)));   memcpy(off, pkt, pktlen);    // fill header   header->tp_len = pktlen;   header->tp_status = tp_status_send_request;    // increase consumer ring pointer   /*ring_offset++;   if(ring_offset >= 1024 * 8) ring_offset = 0;*/    // notify kernel   if (sendto(fd, null, 0, 0, (sockaddr*)txring_daddr, sizeof(sockaddr_ll)) < 0) {     perror("sendto");     return -1;   }    return 0; }  class rawsocket {     public:         inline rawsocket() { }         inline void initialize() {             sockfd = socket(pf_packet, sock_raw, htons(eth_p_ip));              ring = init_packetsock_ring(sockfd, packet_tx_ring);              ifreq ifr;             memset (&ifr, 0, sizeof (ifr));             strncpy((char *) ifr.ifr_name, "eth0", ifnamsiz);             ioctl(sockfd, siocgifindex, &ifr);             int index = ifr.ifr_ifindex;             ioctl(sockfd, siocgifhwaddr, &ifr);              sll = new sockaddr_ll();             sll->sll_family = af_packet;             sll->sll_ifindex = index;             sll->sll_protocol = htons(eth_p_ip);             sll->sll_halen = htons(6);              memcpy(ippacket::our_mac, ifr.ifr_hwaddr.sa_data, eth_alen);             memcpy(sll->sll_addr, ifr.ifr_hwaddr.sa_data, eth_alen);              /*struct packet_mreq mr;             memset (&mr, 0, sizeof (mr));             mr.mr_ifindex = ifr.ifr_ifindex;             mr.mr_type = packet_mr_promisc;             setsockopt(sockfd, sol_packet,packet_add_membership, &mr, sizeof (mr));*/             //setsockopt(sockfd, ipproto_ip, ip_hdrincl, &optval, sizeof(int));         }          inline ~rawsocket() {             close(sockfd);         }          inline void send(const ippacket* ip) const {             process_tx(sockfd, ring, ip->packet_ptr, ip->tot_len, sll);             printf("tx\n");         }     protected:         char *ring;         int sockfd;         sockaddr_ll *sll; };  #endif // rawsocket_h 

ip->packet_ptr being pointer packet containing ethhdr , iphdr , on. packets being correcly sent via "normal" pf_packet sockets. tried using tx ring feature. however, first packet ever gets sent (and gets sent 100% correctly). nothing else seems happen on network layer (tcpdump -vvv -e shows no network traffic @ occuring!) however, sendto() calls processed correctly.

i didnt test functionality myself, think have error in configuring struct tpacket_req fields. _nr fields quite large. see example code (linked wiki ):

/* setup fd mmap() ring buffer */ req.tp_block_size=4096; req.tp_frame_size=1024; req.tp_block_nr=64; req.tp_frame_nr=4*64; if ( (setsockopt(fd,     sol_packet,     packet_rx_ring,     (char *)&req,     sizeof(req))) != 0 ) {     perror("setsockopt()");     close(fd);     return 1; };  /* mmap() sucker */ map=mmap(null,     req.tp_block_size * req.tp_block_nr,     prot_read|prot_write|prot_exec, map_shared, fd, 0); 

Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

javascript - jQuery .height() return 0 when visible but non-0 when hidden -