LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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


Reply
  Search this Thread
Old 11-27-2018, 12:18 AM   #1
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 270

Rep: Reputation: 33
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 ?
 
Old 11-27-2018, 04:48 PM   #2
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: Fedora
Posts: 4,140

Rep: Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263Reputation: 1263
Are you sending to lo or the IP of your NIC? What is in your route table?
 
1 members found this post helpful.
Old 11-27-2018, 05:05 PM   #3
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,263
Blog Entries: 24

Rep: Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194
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.
 
Old 12-25-2018, 07:37 AM   #4
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 270

Original Poster
Rep: Reputation: 33
Quote:
Originally Posted by smallpond View Post
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"
 
Old 12-25-2018, 07:48 AM   #5
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 270

Original Poster
Rep: Reputation: 33
Quote:
Originally Posted by astrogeek View Post
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....!!!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Capturing packets from my WAN/Router {O_o} Linux - Security 4 10-12-2005 04:56 PM
VoIP Packets capturing in linux fastian Linux - Networking 1 03-25-2005 11:34 AM
capturing ethernet packets shrike_912 Programming 5 08-02-2004 01:46 PM
Capturing video with Cinelerra works, capturing video with Xawtv doesn't! seaelf Slackware 0 06-27-2004 05:18 PM
Capturing packets in ethereal as non-root user? maxor Linux - Software 6 08-27-2003 03:05 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:18 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration