LinuxQuestions.org
Share your knowledge at the LQ Wiki.
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 03-14-2020, 03:39 AM   #1
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Rep: Reputation: 32
vlan tag missing in packets captured using custom socket but visible in wireshark


I am using

Code:
read_socket = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
and for writing as well

Code:
write_socket = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
while writing packet, I am writing entire packet
( i.e., ethernet header, ip header, udp header, application data and finally ethernet checksum )

but while capturing on other side using read_socket I am seeing, if it is just ethernet packet, entire packet is visible. But however, if I am sending packet with vlan tag, read_socket is capturing entire packet excluding vlan tag. As it is vlan 1ad packet, the four bytes in ethernet header are missing.

But entire packet is visible in wireshark capture. Tried identifying the socket used by wireshark, but not able to succeed. I downloaded the wireshark source code, kept logs where ever socket function call is there, compiled and used that executable to capture the packets without installing. Because I already have the one installed using "sudo apt", probably installed libraries are being used even though I am running the locally compiled executable.

To my surprise, if I open the read socket after started sending the vlan packets, I am seeing the entire packet is getting captured(i.e., including vlan tag). But If I open the read / write sockets, then start sending the packets, I am seeing vlan tag is missing....!!!

But I can't afford opening read socket after started sending packets, as I will be loosing some packets.
Can someone help me in always capturing the entire packet including vlan tag

Note: Both the network cards are existing in same machine and are connected B2B. Project requirement is to send / receive packets via Tx/Rx queues.

Here is the full code I have written

Code:
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <net/if.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdbool.h>

_Atomic ssize_t total_bytes_written, total_pkts = 0;

char *card1 = "eth0";
char *card2 = "eth1";

const int num_of_threads = 1;
const int pkt_size = 1200;
int write_socket, read_socket;
char *array;

int create_write_sock( char const * const card_name )
{
	const int sock = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
	if( sock == -1 )
	{
		perror( "write socket" );
		exit(EXIT_FAILURE);
	}
	struct sockaddr_ll my_addr =
	{
		.sll_family = AF_PACKET,
		.sll_protocol = htons(ETH_P_ALL),
		.sll_ifindex = if_nametoindex(card_name)
	};
	if( bind( sock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_ll) ) == -1 )
	{
		perror( "bind socket" );
		exit(EXIT_FAILURE);
	}
	if( 0 )
	{
		int one = 1;
		if( setsockopt( sock, SOL_PACKET, PACKET_QDISC_BYPASS, &one, sizeof(one)) < 0 )
		{
			perror( "PACKET_QDISC_BYPASS" );
			exit(EXIT_FAILURE);
		}
	}
	return sock;
}

int create_read_sock( char const * const card_name )
{
	const int sock = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
	if( sock == -1 )
	{
		perror( "read socket" );
		exit(EXIT_FAILURE);
	}
	struct ifreq ifr;
	strncpy( ifr.ifr_name, card_name, IFNAMSIZ );
	if( ioctl( sock, SIOCGIFFLAGS, &ifr ) == -1 )
	{
		perror( "SIOCGIFFLAGS" );
		exit(EXIT_FAILURE);
	}
	ifr.ifr_flags |= ( IFF_PROMISC | IFF_UP );
	if( ioctl( sock, SIOCSIFFLAGS, &ifr ) == -1 )
	{
		perror( "SIOCSIFFLAGS" );
		exit(EXIT_FAILURE);
	}

	struct sockaddr_ll my_addr =
	{
		.sll_family = PF_PACKET,
		.sll_protocol = htons(ETH_P_ALL),
		.sll_ifindex = if_nametoindex(card_name)
	};
	if( bind( sock, (struct sockaddr *)&my_addr, sizeof(my_addr) ) == -1 )
	{
		perror( "bind read socket" );
		exit(EXIT_FAILURE);
	}
	return sock;
}

const _Bool stripping_vlan_tag = true;

void *read_pkts( void *param )
{
	char read_array[2000];
	ssize_t temp_bytes;
	int i, j;
	if( stripping_vlan_tag == false )
		read_socket = create_read_sock( card2 );
	for( i=0; i<5; i++ )
	{
		temp_bytes = read( read_socket, read_array, pkt_size );
		if( temp_bytes == pkt_size )
		{
			if( (uint8_t)read_array[12] == 0x81 )
			{
				if( read_array[13] == 0 )
				{
					printf( "%s %d SUCCESS......!!!!!\n", __func__, __LINE__ );
				}
			}
			else
				printf( "%s %d fail......!!!!!\n", __func__, __LINE__ );
		}
		else
			printf( "%s %d temp bytes: %ld pkt_size: %u fail......!!!!!\n", __func__, __LINE__, temp_bytes, pkt_size );
	}
}

void *write_pkts( void *param )
{
	const int count = 100/num_of_threads;
	ssize_t bytes_written_local = 0, total_pkts_local = 0;
	ssize_t temp_bytes;
	int i;
	for( i=0; i<count; i++ )
	{
		temp_bytes = write( write_socket, array, pkt_size );
		if( temp_bytes == pkt_size )
		{
			total_pkts_local++;
			bytes_written_local += temp_bytes;
		}
		if( temp_bytes < 0 )
		{
			printf( "%s %d local pkts: %ld local bytes: %ld bits: %ld \n", __func__, __LINE__, total_pkts_local, bytes_written_local, bytes_written_local*8 );
			perror( "Unable to write" );
			return NULL;
		}
		else if( temp_bytes < pkt_size )
		{
			printf( "%s %d local pkts: %ld local bytes: %ld bits: %ld \n", __func__, __LINE__, total_pkts_local, bytes_written_local, bytes_written_local*8 );
			perror( "Shouldn't be here." );
			return NULL;
		}
	}
	total_pkts += total_pkts_local;
	total_bytes_written += bytes_written_local;
	//printf( "%s %d success pkts local: %ld bytes local: %ld\n", __func__, __LINE__, total_pkts_local, bytes_written_local );
	return NULL;
}

int main()
{
	write_socket = create_write_sock( card1 );
	if( stripping_vlan_tag == true )
		read_socket = create_read_sock( card2 );
	array = calloc( sizeof(char), pkt_size );
	int i;
	for( i=0; i<pkt_size; i++ )
	{
		array[i] = 'a';
	}
	array[12] = 0x81;
	array[13] = 0;
	array[14] = 0xef;
	array[15] = 0xbd;
	array[16] = 0x08;
	array[17] = 0;

	const time_t t1 = time(NULL);
	pthread_t *write_threads = calloc( sizeof(pthread_t), num_of_threads );
	for( i=0; i<num_of_threads; i++ )
	{
		pthread_create( &write_threads[i], NULL, write_pkts, NULL );
	}
	pthread_t read_thread;
	pthread_create( &read_thread, NULL, read_pkts, NULL );
	for( i=0; i<num_of_threads; i++ )
	{
		pthread_join( write_threads[i], NULL );
	}
	const time_t t2 = time(NULL);

	printf("time: %ldsecs thread count: %d card: %s packet_size: %d pkts: %ld total bytes: %ld ", t2-t1, num_of_threads, card1, pkt_size, total_pkts, total_bytes_written );

	const uint32_t KILO = 1000;
	const double giga = KILO*KILO*KILO, mega = KILO*KILO;
	const uint64_t value = total_bytes_written*8;

	if( value >= giga )
		printf( "%.02fGbps", (double)value/giga/(t2-t1) );
	else if( value > mega )
		printf( "%.02fMbps", (double)value/mega/(t2-t1) );
	else if( value > KILO )
		printf( "%.02fKbps", (double)value/KILO/(t2-t1) );
	else
		printf( "%.02fbps", (double)value/(t2-t1) );
	printf( "\n" );
}

Last edited by chakka.lokesh; 03-14-2020 at 04:51 AM.
 
Old 03-14-2020, 08:55 AM   #2
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 247

Rep: Reputation: Disabled
It seems likely that the driver for the receiving NIC is stripping the VLAN tag. Have you tried switching which card is sending and which is receiving?
 
Old 03-17-2020, 04:13 AM   #3
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Original Poster
Rep: Reputation: 32
Tried switching read / write cards.
Same behavior. wireshark is capturing 1200 bytes. But the socket in my code is capturing only 1196 bytes(stripping vlan tag).

device driver information is

Code:
$ ethtool -i eth0
driver: r8169
version: 
firmware-version: rtl_nic/rtl8168e-2.fw
expansion-rom-version: 
bus-info: 0000:05:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no
Code:
$ ethtool -i eth1
driver: r8152
version: v1.09.10
firmware-version: 
expansion-rom-version: 
bus-info: usb-0000:00:1a.0-1.1
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
 
Old 03-17-2020, 07:40 AM   #4
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 247

Rep: Reputation: Disabled
Maybe this will help: https://askubuntu.com/questions/5449...t-by-linux-box
 
Old 03-20-2020, 03:14 AM   #5
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by SoftSprocket View Post
No. Because socket is not able to capture. But wireshark is capturing in the same environment...!!!
 
Old 03-20-2020, 08:18 AM   #6
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 247

Rep: Reputation: Disabled
Quote:
Originally Posted by chakka.lokesh View Post
No. Because socket is not able to capture. But wireshark is capturing in the same environment...!!!
libpcap (which wireshark uses) is operating at a lower level then your application. It grabs packets directly from the network card. So, your comment would imply the advice in the link might help you.

Last edited by SoftSprocket; 03-20-2020 at 08:21 AM.
 
2 members found this post helpful.
Old 03-24-2020, 02:59 AM   #7
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by SoftSprocket View Post
libpcap (which wireshark uses) is operating at a lower level then your application. It grabs packets directly from the network card. So, your comment would imply the advice in the link might help you.
I have already tried that link before posting the question. It didn't worked.
However, as per my understanding, libpcap is capable of capturing packet directly from network card using the same type of socket which I am also using.
Please refer to pcap-linux.c

Another relevant link I have found....

https://bugzilla.redhat.com/show_bug.cgi?id=1264316

It seems there is a different way to deal with this issue...!!!
I am trying as per above clues....

Last edited by chakka.lokesh; 03-24-2020 at 03:24 AM.
 
Old 03-24-2020, 08:09 AM   #8
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 247

Rep: Reputation: Disabled
I think that libpcap uses mmap whenever possible but I was mistaken in that it is available in user space so unlikely the solution.
https://www.kernel.org/doc/Documenta...acket_mmap.txt

I suspect you are onto the problem now:
https://developerweb.net/viewtopic.php?id=7396
https://www.cyberciti.biz/tips/howto...work-vlan.html
 
Old 03-26-2020, 01:04 AM   #9
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by SoftSprocket View Post
I suspect you are onto the problem now:
https://developerweb.net/viewtopic.php?id=7396
this link is unavailable...!!!

Quote:
Originally Posted by SoftSprocket View Post
Configuration should be proper if I am consuming vlan services from operating system. I feel, this is not relevant to my requirement as I am working on raw packets.
 
Old 03-26-2020, 05:48 AM   #10
boughtonp
Member
 
Registered: Feb 2007
Location: UK
Distribution: Debian
Posts: 316

Rep: Reputation: 186Reputation: 186
Quote:
Originally Posted by chakka.lokesh View Post
this link is unavailable...!!!
There's a copy in the web archive: https://web.archive.org/web/20170627041949/developerweb.net/viewtopic.php?id=7396

 
Old 03-29-2020, 02:53 AM   #11
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by boughtonp View Post
Tried. same issue. 4 bytes are being stripped....!!!
 
Old 03-30-2020, 01:58 AM   #12
chakka.lokesh
Member
 
Registered: Mar 2008
Distribution: Ubuntu
Posts: 258

Original Poster
Rep: Reputation: 32
Lightbulb

finally got the solution....!!!!

thanks for the support.

Code:
//gcc filename.c -lpthread && sudo ./a.out

#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <net/if.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdbool.h>

_Atomic ssize_t total_bytes_written, total_pkts = 0;

char *write_card = "enp5s0";
char *read_card = "enx00e04c680189";

const int num_of_threads = 1;
const int pkt_size = 1200;
int write_socket, read_socket;
char *array;

int create_write_sock( char const * const card_name )
{
	const int sock = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
	if( sock == -1 )
	{
		perror( "write socket" );
		exit(EXIT_FAILURE);
	}
	struct sockaddr_ll my_addr =
	{
		.sll_family = AF_PACKET,
		.sll_protocol = htons(ETH_P_ALL),
		.sll_ifindex = if_nametoindex(card_name)
	};
	if( bind( sock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_ll) ) == -1 )
	{
		perror( "bind socket" );
		exit(EXIT_FAILURE);
	}
	return sock;
}

int create_read_sock( char const * const card_name )
{
	const int sock = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );//Lokesh experiment with zero instead of ETH_P_ALL
	if( sock == -1 )
	{
		perror( "read socket" );
		exit(EXIT_FAILURE);
	}
	struct ifreq ifr;
	strncpy( ifr.ifr_name, card_name, IFNAMSIZ );
	if( ioctl( sock, SIOCGIFFLAGS, &ifr ) == -1 )
	{
		perror( "SIOCGIFFLAGS" );
		exit(EXIT_FAILURE);
	}
	ifr.ifr_flags |= ( IFF_PROMISC | IFF_UP );
	if( ioctl( sock, SIOCSIFFLAGS, &ifr ) == -1 )
	{
		perror( "SIOCSIFFLAGS" );
		exit(EXIT_FAILURE);
	}

	struct sockaddr_ll my_addr =
	{
		.sll_family = PF_PACKET,
		.sll_protocol = htons(ETH_P_ALL),
		.sll_ifindex = if_nametoindex(card_name)
	};
	if( bind( sock, (struct sockaddr *)&my_addr, sizeof(my_addr) ) == -1 )
	{
		perror( "bind read socket" );
		exit(EXIT_FAILURE);
	}
	int one = 1;
	if( setsockopt( sock, SOL_PACKET, PACKET_AUXDATA, &one, sizeof(one)) < 0 )
	{
		perror( "read socket PACKET_AUXDATA" );
		exit(EXIT_FAILURE);
	}
	return sock;
}

const _Bool stripping_vlan_tag = true;

//https://seclists.org/tcpdump/2008/q3/35
//https://en.wikipedia.org/wiki/IEEE_802.1Q
void *read_pkts( void *param )
{
	char read_array[2000];
	ssize_t temp_bytes;
	struct iovec iov = { .iov_base = read_array, .iov_len = 2000 };
	struct cmsghdr *cmsg_ptr;
	union
	{
		struct cmsghdr  cmsg;
		char            buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
	}cmsg_buf;
	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = &cmsg_buf, .msg_controllen = sizeof(cmsg_buf) };
	struct tpacket_auxdata *aux_ptr;
	int i, j;

	if( stripping_vlan_tag == false )
		read_socket = create_read_sock( read_card );

	for( i=0; i<5; i++ )//reading only five packets....!!!
	{
		temp_bytes = recvmsg( read_socket, &msg, 0 );
		printf( "\ntemp_bytes: %ld first 30 bytes:\n", temp_bytes );
		for( j=0; j<30; j++ )
		{
			printf( "%02X ", (uint8_t) read_array[j] );
		}
		printf( "\n" );
		for( cmsg_ptr = CMSG_FIRSTHDR(&msg); cmsg_ptr; cmsg_ptr = CMSG_NXTHDR( &msg, cmsg_ptr ) )
		{
			if( ( cmsg_ptr->cmsg_len < CMSG_LEN( sizeof( struct tpacket_auxdata ) ) ) ||
					( cmsg_ptr->cmsg_level != SOL_PACKET ) ||
					( cmsg_ptr->cmsg_type != PACKET_AUXDATA ) )
				continue;
			aux_ptr = (struct tpacket_auxdata *)CMSG_DATA(cmsg_ptr);
			if( aux_ptr->tp_vlan_tci == 0 )
			{
				printf( "%s %d vlan tag missing\n", __func__, __LINE__ );
				continue;
			}
			printf( "%s %d tpid: %04X tci: %04X\n", __func__, __LINE__, aux_ptr->tp_vlan_tpid, aux_ptr->tp_vlan_tci );
		}
		printf( "\n====end====\n" );

		if( temp_bytes == pkt_size )
		{
			if( (uint8_t)read_array[12] == 0x81 )
			{
				if( read_array[13] == 0 )
				{
					printf( "%s %d SUCCESS......!!!!!\n", __func__, __LINE__ );
				}
			}
			else
				printf( "%s %d fail......!!!!!\n", __func__, __LINE__ );
		}
		else
			printf( "%s %d temp bytes: %ld pkt_size: %u fail......!!!!!\n", __func__, __LINE__, temp_bytes, pkt_size );
	}
}

void *write_pkts( void *param )
{
	const int count = 1000000/num_of_threads;
	ssize_t bytes_written_local = 0, total_pkts_local = 0;
	ssize_t temp_bytes;
	int i;
	for( i=0; i<count; i++ )
	{
		temp_bytes = write( write_socket, array, pkt_size );
		if( temp_bytes == pkt_size )
		{
			total_pkts_local++;
			bytes_written_local += temp_bytes;
		}
		if( temp_bytes < 0 )
		{
			printf( "%s %d local pkts: %ld local bytes: %ld bits: %ld \n", __func__, __LINE__, total_pkts_local, bytes_written_local, bytes_written_local*8 );
			perror( "Unable to write" );
			return NULL;
		}
		else if( temp_bytes < pkt_size )
		{
			printf( "%s %d local pkts: %ld local bytes: %ld bits: %ld \n", __func__, __LINE__, total_pkts_local, bytes_written_local, bytes_written_local*8 );
			perror( "Shouldn't be here." );
			return NULL;
		}
	}
	total_pkts += total_pkts_local;
	total_bytes_written += bytes_written_local;
	//printf( "%s %d success pkts local: %ld bytes local: %ld\n", __func__, __LINE__, total_pkts_local, bytes_written_local );
	return NULL;
}

int main()
{
	write_socket = create_write_sock( write_card );
	if( stripping_vlan_tag == true )
		read_socket = create_read_sock( read_card );
	array = calloc( sizeof(char), pkt_size );
	int i;
	for( i=0; i<pkt_size; i++ )
	{
		array[i] = 'a';
	}
	i = 12;
	if( 1 )
	{//vlan 1ad
		array[i] = 0x88;
		i++;
		array[i] = 0xA8;
		i++;
		array[i] = 0x01;
		i++;
		array[i] = 0x02;
		i++;
	}
	array[i] = 0x81;
	i++;
	array[i] = 0;
	i++;
	array[i] = 0x03;
	i++;
	array[i] = 0x04;
	i++;
	array[i] = 0x08;
	i++;
	array[i] = 0;

	const time_t t1 = time(NULL);
	pthread_t *write_threads = calloc( sizeof(pthread_t), num_of_threads );
	for( i=0; i<num_of_threads; i++ )
	{
		pthread_create( &write_threads[i], NULL, write_pkts, NULL );
	}
	pthread_t read_thread;
	pthread_create( &read_thread, NULL, read_pkts, NULL );
	for( i=0; i<num_of_threads; i++ )
	{
		pthread_join( write_threads[i], NULL );
	}
	const time_t t2 = time(NULL);

	printf("time: %ldsecs thread count: %d card: %s packet_size: %d pkts: %ld total bytes: %ld ", t2-t1, num_of_threads, write_card, pkt_size, total_pkts, total_bytes_written );

	const uint32_t KILO = 1000;
	const double giga = KILO*KILO*KILO, mega = KILO*KILO;
	const uint64_t value = total_bytes_written*8;

	if( value >= giga )
		printf( "%.02fGbps", (double)value/giga/(t2-t1) );
	else if( value > mega )
		printf( "%.02fMbps", (double)value/mega/(t2-t1) );
	else if( value > KILO )
		printf( "%.02fKbps", (double)value/KILO/(t2-t1) );
	else
		printf( "%.02fbps", (double)value/(t2-t1) );
	printf( "\n" );
}
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
Modify UDP receive socket buffer size for an open socket (not at system level, but socket level) barz_83_LQ Linux - Networking 2 11-27-2017 07:56 PM
Why can't captured post data such as name and passwd with firebug or wireshark? luofeiyu Linux - Networking 1 02-01-2017 07:55 AM
Question on using Wireshark to troubleshoot vlan traffic JockVSJock Linux - Networking 6 09-30-2016 12:40 PM
Sending ethernet packet with VLAN tag in C socket Praju26 Linux - Networking 9 07-01-2015 06:34 PM
Wireshark UDP Packets Socket not set robtard Programming 3 10-27-2010 05:45 PM

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

All times are GMT -5. The time now is 07:06 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration