Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to
LinuxQuestions.org , a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free.
Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please
contact us . If you need to reset your password,
click here .
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a
virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month.
Click here for more info.
11-27-2018, 12:18 AM
#1
Member
Registered: Mar 2008
Distribution: Ubuntu
Posts: 270
Rep:
RX_RING is capturing TX_RING packets
after referring to the following two links,
https://www.kernel.org/doc/Documenta...acket_mmap.txt
https://sites.google.com/site/packetmmap/
I have written a code with two threads to read and write packets using RX/TX ring.
Both are running in parallel.
To my surprise, I am seeing packets that are being written by TX thread are showing up in RX thread as received packets.
code is as follows:
Code:
//gcc packet_mmap_read_write.c -lpthread
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#include <net/if.h>
#include <net/if.h>
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
#include <poll.h>
char const * const card_name = "eth0";
void *rx_ring_code( void *unused_param )
{
int i;
const int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if( sock < 0 )
{
perror("socket");
exit(1);
}
i = TPACKET_V3;
if( setsockopt( sock, SOL_PACKET, PACKET_VERSION, &i, sizeof(i) ) < 0 )
{
perror("setsockopt");
exit(1);
}
/* i = ( ( getpid() & 0xffff ) | (PACKET_FANOUT_CPU << 16));
if( setsockopt( sock, SOL_PACKET, PACKET_FANOUT, &i, sizeof(i) ) < 0 )
{
perror("setsockopt");
return NULL;
}
*/
struct tpacket_req3 req =
{
.tp_block_size = 1 << 22,
.tp_frame_size = 1 << 11,
.tp_block_nr = 64,
};
struct ifreq ifr;
strcpy( ifr.ifr_name, card_name );
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
{
perror("unable to get flags");
return NULL;
}
ifr.ifr_flags |= ( IFF_PROMISC | IFF_UP );
if( ioctl( sock, SIOCSIFFLAGS, &ifr ) == -1 )
{
perror("unable to set flags");
return NULL;
}
req.tp_frame_nr = (req.tp_block_size * req.tp_block_nr) / req.tp_frame_size;
if( setsockopt( sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(struct tpacket_req3) ) < 0 )
{
perror("setsockopt");
exit(1);
}
uint8_t *const map = mmap( NULL, req.tp_block_size * req.tp_block_nr, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_LOCKED, sock, 0 );
if( map == MAP_FAILED )
{
perror("mmap");
exit(1);
}
struct sockaddr_ll ll =
{
.sll_family = PF_PACKET,
.sll_protocol = htons(ETH_P_ALL),
.sll_ifindex = if_nametoindex(ifr.ifr_name)
};
if (bind(sock, (struct sockaddr *) &ll, sizeof(ll)) < 0)
{
perror("bind");
exit(1);
}
struct pollfd pfd =
{
.fd = sock,
.events = POLLIN | POLLERR,
.revents = 0
};
int block_pos = 0;
int pkt_num = 0;
for( block_pos = 0; 1; block_pos = ((block_pos+1) % req.tp_block_nr) )
{
struct block_desc
{
uint32_t version;
uint32_t offset_to_priv;
struct tpacket_hdr_v1 h1;
} *pbd = (struct block_desc *) ( map + (block_pos * req.tp_block_size) );
if( ( pbd->h1.block_status & TP_STATUS_USER ) == 0 )
{
poll(&pfd, 1, -1);
continue;
}
printf( "number of packets captured: %d\n", pbd->h1.num_pkts );
struct tpacket3_hdr *ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + pbd->h1.offset_to_first_pkt);
for( i = 0; i<pbd->h1.num_pkts; i++ )
{
printf( "packet Number: %d packet size: %d\n", pkt_num++, ppd->tp_snaplen );
/*uint8_t *pkt_ptr = ((uint8_t *) ppd + ppd->tp_mac);
int j;
for( j=0; j<ppd->tp_snaplen; j++ )
{
printf( "%02X ", pkt_ptr[j] );
}
printf( "\n" );
ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + ppd->tp_next_offset);*/
}
pbd->h1.block_status = TP_STATUS_KERNEL;
}
munmap(map, req.tp_block_size * req.tp_block_nr);
close(sock);
return 0;
}
void * tx_ring_code( void *unused_param )
{
const int c_packet_sz = 200;
int fd_socket, j;
uint32_t i;
fd_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if( fd_socket == -1 )
{
perror("socket");
return NULL;
}
struct sockaddr_ll my_addr =
{
.sll_family = AF_PACKET,
.sll_protocol = htons(ETH_P_ALL),
.sll_ifindex = (int)if_nametoindex(card_name)
};
/* bind port */
if( bind( fd_socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_ll) ) == -1 )
{
perror("bind");
return NULL;
}
/* prepare Tx ring request */
struct tpacket_req s_packet_req =
{
.tp_block_size = 1<<12,
.tp_frame_size = 1<<12,
.tp_block_nr = 10
};
s_packet_req.tp_frame_nr = (s_packet_req.tp_block_size*s_packet_req.tp_block_nr)/s_packet_req.tp_frame_size;
/* send TX ring request */
if( setsockopt( fd_socket, SOL_PACKET, PACKET_TX_RING, (char *)&s_packet_req, sizeof(s_packet_req) ) < 0 )
{
perror( "setsockopt: PACKET_TX_RING" );
return NULL;
}
/* mmap Tx ring buffers memory */
struct tpacket_hdr * const map = mmap(0, s_packet_req.tp_block_size * s_packet_req.tp_block_nr, PROT_WRITE, MAP_SHARED, fd_socket, 0);
if( map == MAP_FAILED )
{
perror("mmap");
return NULL;
}
for( i=0; i<s_packet_req.tp_block_nr; i++ )
{
struct tpacket_hdr * ps_header = ((struct tpacket_hdr *)((void *)map + (s_packet_req.tp_block_size*i)));
#define my_TPACKET_ALIGN(x) (((x)+(uint64_t)(TPACKET_ALIGNMENT-1))&~((uint64_t)(TPACKET_ALIGNMENT-1)))
char * pkt_ptr = ((void*) ps_header) + my_TPACKET_ALIGN(sizeof(struct tpacket_hdr));
for( j=0; j<c_packet_sz; j++ )
{
pkt_ptr[j] = j; /* fill data in buffer */
}
/* update packet length */
ps_header->tp_len = (uint32_t)c_packet_sz;
ps_header->tp_status = TP_STATUS_SEND_REQUEST;
}
int total_pkts = 0, ec_send, total_bytes = 0;
while( total_pkts<s_packet_req.tp_block_nr )
{
ec_send = sendto( fd_socket, NULL, 0, MSG_DONTWAIT, NULL, sizeof(struct sockaddr_ll) );
if(ec_send < 0)
{
perror("send");
}
else
{
total_pkts += ec_send/(c_packet_sz);
total_bytes += ec_send;
printf("%s %d send %d packets (+%d bytes)\n", __func__, __LINE__, total_pkts, total_bytes );
}
}
munmap( map, s_packet_req.tp_block_size * s_packet_req.tp_block_nr );
close(fd_socket);
return NULL;
}
int main()
{
pthread_t rx_thread, tx_thread;
if( pthread_create( &rx_thread, NULL, rx_ring_code, NULL ) )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
return EXIT_FAILURE;
}
if( pthread_create( &tx_thread, NULL, tx_ring_code, NULL ) )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
return EXIT_FAILURE;
}
if( pthread_join( rx_thread, NULL ) )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
return EXIT_FAILURE;
}
if( pthread_join( tx_thread, NULL ) )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
return EXIT_FAILURE;
}
}
Can some one help me if there is a way to capture only incoming packets ?
11-27-2018, 04:48 PM
#2
Senior Member
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: Fedora
Posts: 4,140
Are you sending to lo or the IP of your NIC? What is in your route table?
1 members found this post helpful.
11-27-2018, 05:05 PM
#3
Moderator
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,263
It would be helpful if you would provide a little more detail to help others quickly understand the problem.
As asked by smallpond, how exactly are you sending your test packets, including routing paths?
Also, if you would include a little information on what you have already done to diagnose the problem it would probably help communicate your view of the problem more readily to those not immediately familiar with the libs you are using, and guide them to a faster understanding of the code and the problem at hand.
12-25-2018, 07:37 AM
#4
Member
Registered: Mar 2008
Distribution: Ubuntu
Posts: 270
Original Poster
Rep:
Quote:
Originally Posted by
smallpond
Are you sending to lo or the IP of your NIC? What is in your route table?
I am sending to NIC. Please the beginning of the code I am using "eth0"
12-25-2018, 07:48 AM
#5
Member
Registered: Mar 2008
Distribution: Ubuntu
Posts: 270
Original Poster
Rep:
Quote:
Originally Posted by
astrogeek
As asked by smallpond, how exactly are you sending your test packets, including routing paths?
I am just sending raw packets. Not related to any routing path.
However, Problem is partially solved with following modification
Code:
/* send TX ring request */
if( setsockopt( fd_socket, SOL_PACKET, PACKET_TX_RING, (char *)&s_packet_req, sizeof(s_packet_req) ) < 0 )
{
perror( "setsockopt: PACKET_TX_RING" );
return NULL;
}
+ int one = 1;
+ if( setsockopt(fd_socket, SOL_PACKET, PACKET_QDISC_BYPASS, &one, sizeof(one)) < 0 )
+ {
+ perror( "setsockopt: PACKET_QDISC_BYPASS" ); return EXIT_FAILURE;
+ }
/* mmap Tx ring buffers memory */
struct tpacket_hdr * const map = mmap(0, s_packet_req.tp_block_size * s_packet_req.tp_block_nr, PROT_WRITE, MAP_SHARED, fd_socket, 0);
if( map == MAP_FAILED )
{
after adding PACKET_QDISC_BYPASS, packets are not visible in RX_Ring but only a few packets are being written by TX thread/ring. Remaining packets are getting stuck in TX ring and while loop is going infinitely....!!!
All times are GMT -5. The time now is 11:18 AM .
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know .
Latest Threads
LQ News