LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking > Linux - Wireless Networking
User Name
Password
Linux - Wireless Networking This forum is for the discussion of wireless networking in Linux.

Notices


Reply
  Search this Thread
Old 01-05-2008, 10:47 AM   #1
saioha
LQ Newbie
 
Registered: Jan 2008
Posts: 1

Rep: Reputation: Disabled
Smile ioctl call for obtaining the RSSI


Hello, my name is Saioa and I am new in the forum, but I have a problem and I wonder if you could help me.

I have installed an Ad-Hoc network with several PCs, for proving over them the routing protocol called OLSR. For doing this I have used the WiFi card of Netgear WG311v3.
The problem is that I need to obtain the received signal power, RSSI, in my computer from the driver every time a new message of the other nodes arrives.
I work over Linux. I have tried to read this value from the file /proc/net/wireless, but this way is not valid as the information of this file is updated more slowly than I receive the messages. I know that the signal power can also be obtained by using ioctl calls, but I don’t know exactly which ioctl I must use. I would also like to know in which unit would this ioctl give me the value, and if there is any way of getting it in dBm. But this matter is secondary, the most important for me is to know which ioctl I have to use to obtain the signal power.

Thank you very much, bye.
 
Old 01-05-2008, 09:30 PM   #2
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by saioha View Post
I have tried to read this value from the file /proc/net/wireless, but this way is not valid as the information of this file is updated more slowly than I receive the messages.
The file is not “updated” any more slowly than it is read. As you may know, the proc filesystem is a virtual filesystem. Every time a process reads from one of the virtual files which reside on that filesystem, an interface to the kernel is called. There is no caching (at least not by the kernel). Your shell or C library might cache the reads, so you might try rewinding the stream associated with the open file descriptor.

Anyway, the update interval is driver-specific, and if you told us what driver you are using, it might even be patchable. Using ioctls and reading from /proc/net/wireless are equivalent except for specification of units and clearing the update indicator flags, which is also driver dependent (more on this later).
Quote:
Originally Posted by saioha View Post
I know that the signal power can also be obtained by using ioctl calls, but I don’t know exactly which ioctl I must use. I would also like to know in which unit would this ioctl give me the value, and if there is any way of getting it in dBm. But this matter is secondary, the most important for me is to know which ioctl I have to use to obtain the signal power.
Well, the ioctl to use goes by the macro SIOCGIWSTATS (mnemonically, Socket IOCtl Get Inet Wireless STATisticS). It is a socket ioctl which means that instead of a descriptor to a normal file, the first argument is a socket file descriptor (any socket will do since we don’t modify any socket attributes). The WE API specifies that the third argument of any ioctl of the form SIOC?IW* will be a pointer to a struct iwreq, and in this case, the interface name is given. Here is a small sample program which will attempt to perform the ioctl, and upon success, it will print the signal level, tell you whether or not it is in dBm, and tell you whether the value was updated.
Code:
#include <linux/wireless.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <stdio.h>
#include <stdlib.h>

/* The name of the interface */
#ifndef IW_NAME
#define IW_NAME "eth1"
#endif

int main()
{
	int sockfd;
	struct iw_statistics stats;
	struct iwreq req = {
		.ifr_name = IW_NAME,
		.u.data = {
			.pointer = &stats,
#ifdef CLEAR_UPDATED
			.flags = 1
#endif
		}
	};

	/* Any old socket will do, and a datagram socket is pretty cheap */
	if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		perror("Could not create simple datagram socket");
		exit(EXIT_FAILURE);
	}

	/* Perform the ioctl */
	if(ioctl(sockfd, SIOCGIWSTATS, &req) == -1) {
		perror("Error performing SIOCGIWSTATS on " IW_NAME);
		close(sockfd);
		exit(EXIT_FAILURE);
	}

	close(sockfd);

	printf("Signal level%s is %d%s.\n",
	       (stats.qual.updated & IW_QUAL_DBM ? " (in dBm)" :""),
	       stats.qual.level,
	       (stats.qual.updated & IW_QUAL_LEVEL_UPDATED ? " (updated)" :""));

	return 0;
}
The code is self-explanatory except for a few parts. The field stats.qual.updated holds a bunch of flags. One of the bits (specifically IW_QUAL_DBM) tells if the quality values (both level and noise) are reported with units of dBm. Most modern drivers will set this bit and you will know the levels exactly in dBm. Some modern drivers will intentionally not set this bit to indicate a different form of measurement (usually a percentage value). Some older drivers do not know about that flag, so the units could be anything.

The other bit we are concerned with is IW_QUAL_LEVEL_UPDATED, which is supposed to tell us if the value has been updated. This is the same as the presence of a dot after a number in the output of /proc/net/wireless. We can modify whether we want all the flags of the form IW_QUAL_*_UPDATED to be cleared by setting the req.u.data.flags field to nonzero. The flags are not only cleared in the copy of the statistics record given to your process, but also in the driver’s record itself. The meaning of this clearing of these bits is driver-specific. I have left this feature in as conditionally compilable (if you pass the option -DCLEAR_UPDATED to your compiler). The behavior when reading from the procfile is to clear the flags. A side effect when you clear the flags with the ioctl which is not present when using the procfile is that you lose any information about whether the flag was previously set.
 
Old 07-31-2008, 06:48 PM   #3
Jessard
Member
 
Registered: Jun 2005
Location: Boston, USA
Distribution: Gentoo, CentOS
Posts: 82

Rep: Reputation: 16
Quote:
Originally Posted by osor View Post
Here is a small sample program which will attempt to perform the ioctl, and upon success, it will print the signal level, tell you whether or not it is in dBm, and tell you whether the value was updated.
Hello osor,

I'm trying to learn some things along the same lines as saioha, so I compiled and ran your example program, but for me the ioctl call fails with:

"Error performing SIOCGIWSTATS on ath0: Argument list too long"

(Of course, I'm assuming I was correct to change eth1 to ath0, in my case... using wifi0 yields "Operation not supported.")

Any tips?

(P.S: I'm using an Atheros AR5BMB5 transmitter module / AR5005GS chipset with the MadWifi 0.9.4 driver)

Last edited by Jessard; 07-31-2008 at 06:58 PM. Reason: Adding hardware/driver information...
 
Old 06-24-2009, 02:36 AM   #4
wes314
LQ Newbie
 
Registered: Jun 2009
Posts: 1

Rep: Reputation: 0
Quote:
Originally Posted by Jessard View Post
Hello osor,

I'm trying to learn some things along the same lines as saioha, so I compiled and ran your example program, but for me the ioctl call fails with:

"Error performing SIOCGIWSTATS on ath0: Argument list too long"

(Of course, I'm assuming I was correct to change eth1 to ath0, in my case... using wifi0 yields "Operation not supported.")

Any tips?

(P.S: I'm using an Atheros AR5BMB5 transmitter module / AR5005GS chipset with the MadWifi 0.9.4 driver)

>>>>>>>


To fix that error i tracked it down to having an invalid length.
You can fix it by adding this:

req.u.data.length = sizeof(iw_statistics);



The following code works for me:

int main()
{
int sockfd;
struct iw_statistics stats;
struct iwreq req;
memset(&stats, 0, sizeof(stats));
memset(&req, 0, sizeof(iwreq));
sprintf(req.ifr_name, "rausb0");
req.u.data.pointer = &stats;
req.u.data.length = sizeof(iw_statistics);
#ifdef CLEAR_UPDATED
req.u.data.flags = 1;
#endif

/* Any old socket will do, and a datagram socket is pretty cheap */
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Could not create simple datagram socket");
exit(EXIT_FAILURE);
}

/* Perform the ioctl */
if(ioctl(sockfd, SIOCGIWSTATS, &req) == -1) {
perror("Error performing SIOCGIWSTATS");
close(sockfd);
exit(EXIT_FAILURE);
}

close(sockfd);

printf("Signal level%s is %d%s.\n",
(stats.qual.updated & IW_QUAL_DBM ? " (in dBm)" :""),
stats.qual.level,
(stats.qual.updated & IW_QUAL_LEVEL_UPDATED ? " (updated)" :""));

return 0;
}

Output with my hand moving around the antenna:

Signal level is 203.
# ./wifi_signal
Signal level is 203.
# ./wifi_signal
Signal level is 203.
# ./wifi_signal
Signal level is 203.
# ./wifi_signal
Signal level is 213.
# ./wifi_signal
Signal level is 217.
# ./wifi_signal
Signal level is 215.
# ./wifi_signal
Signal level is 217.
# ./wifi_signal
Signal level is 217.
 
Old 07-09-2009, 10:21 AM   #5
bogd4n.iv4n
LQ Newbie
 
Registered: Jul 2009
Posts: 2

Rep: Reputation: 0
Code doesn't compile

I compiled your code wes314 and I got the following errors:

In file included from /usr/include/linux/wireless.h:74,
from test.c:1:
/usr/include/linux/if.h:168: error: field ‘ifru_addr’ has incomplete type
/usr/include/linux/if.h:169: error: field ‘ifru_dstaddr’ has incomplete type
/usr/include/linux/if.h:170: error: field ‘ifru_broadaddr’ has incomplete type
/usr/include/linux/if.h:171: error: field ‘ifru_netmask’ has incomplete type
/usr/include/linux/if.h:172: error: field ‘ifru_hwaddr’ has incomplete type
In file included from test.c:1:
/usr/include/linux/wireless.h:739: error: field ‘addr’ has incomplete type
/usr/include/linux/wireless.h:765: error: field ‘bssid’ has incomplete type
/usr/include/linux/wireless.h:823: error: field ‘addr’ has incomplete type
/usr/include/linux/wireless.h:836: error: field ‘addr’ has incomplete type
/usr/include/linux/wireless.h:849: error: field ‘bssid’ has incomplete type
/usr/include/linux/wireless.h:857: error: field ‘src_addr’ has incomplete type
/usr/include/linux/wireless.h:868: error: field ‘bssid’ has incomplete type
/usr/include/linux/wireless.h:922: error: field ‘ap_addr’ has incomplete type
/usr/include/linux/wireless.h:923: error: field ‘addr’ has incomplete type
test.c: In function ‘main’:
test.c:18: warning: incompatible implicit declaration of built-in function ‘memset’
test.c:19: error: ‘iwreq’ undeclared (first use in this function)
test.c:19: error: (Each undeclared identifier is reported only once
test.c:19: error: for each function it appears in.)
test.c:22: error: ‘iw_statistics’ undeclared (first use in this function)

Please help.
 
Old 10-19-2009, 07:45 AM   #6
peiweijun
LQ Newbie
 
Registered: May 2009
Posts: 3

Rep: Reputation: 0
Quote:
Originally Posted by bogd4n.iv4n View Post
I compiled your code wes314 and I got the following errors:

In file included from /usr/include/linux/wireless.h:74,
from test.c:1:
/usr/include/linux/if.h:168: error: field ‘ifru_addr’ has incomplete type
/usr/include/linux/if.h:169: error: field ‘ifru_dstaddr’ has incomplete type
/usr/include/linux/if.h:170: error: field ‘ifru_broadaddr’ has incomplete type
/usr/include/linux/if.h:171: error: field ‘ifru_netmask’ has incomplete type
/usr/include/linux/if.h:172: error: field ‘ifru_hwaddr’ has incomplete type
In file included from test.c:1:
/usr/include/linux/wireless.h:739: error: field ‘addr’ has incomplete type
/usr/include/linux/wireless.h:765: error: field ‘bssid’ has incomplete type
/usr/include/linux/wireless.h:823: error: field ‘addr’ has incomplete type
/usr/include/linux/wireless.h:836: error: field ‘addr’ has incomplete type
/usr/include/linux/wireless.h:849: error: field ‘bssid’ has incomplete type
/usr/include/linux/wireless.h:857: error: field ‘src_addr’ has incomplete type
/usr/include/linux/wireless.h:868: error: field ‘bssid’ has incomplete type
/usr/include/linux/wireless.h:922: error: field ‘ap_addr’ has incomplete type
/usr/include/linux/wireless.h:923: error: field ‘addr’ has incomplete type
test.c: In function ‘main’:
test.c:18: warning: incompatible implicit declaration of built-in function ‘memset’
test.c:19: error: ‘iwreq’ undeclared (first use in this function)
test.c:19: error: (Each undeclared identifier is reported only once
test.c:19: error: for each function it appears in.)
test.c:22: error: ‘iw_statistics’ undeclared (first use in this function)

Please help.
move
"#include <sys/types.h>
#include <sys/socket.h>"
to the front of
"#include <wireless.h>"
 
Old 06-17-2010, 10:35 AM   #7
aztroboy
LQ Newbie
 
Registered: Jun 2010
Posts: 19

Rep: Reputation: 0
the meaning of those signal values?

Quote:
Originally Posted by wes314 View Post
>>>>>>>


To fix that error i tracked it down to having an invalid length.
You can fix it by adding this:

req.u.data.length = sizeof(iw_statistics);



The following code works for me:

int main()
{
int sockfd;
struct iw_statistics stats;
struct iwreq req;
memset(&stats, 0, sizeof(stats));
memset(&req, 0, sizeof(iwreq));
sprintf(req.ifr_name, "rausb0");
req.u.data.pointer = &stats;
req.u.data.length = sizeof(iw_statistics);
#ifdef CLEAR_UPDATED
req.u.data.flags = 1;
#endif

/* Any old socket will do, and a datagram socket is pretty cheap */
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Could not create simple datagram socket");
exit(EXIT_FAILURE);
}

/* Perform the ioctl */
if(ioctl(sockfd, SIOCGIWSTATS, &req) == -1) {
perror("Error performing SIOCGIWSTATS");
close(sockfd);
exit(EXIT_FAILURE);
}

close(sockfd);

printf("Signal level%s is %d%s.\n",
(stats.qual.updated & IW_QUAL_DBM ? " (in dBm)" :""),
stats.qual.level,
(stats.qual.updated & IW_QUAL_LEVEL_UPDATED ? " (updated)" :""));

return 0;
}

Output with my hand moving around the antenna:

Signal level is 203.
# ./wifi_signal
Signal level is 203.
# ./wifi_signal
Signal level is 203.
# ./wifi_signal
Signal level is 203.
# ./wifi_signal
Signal level is 213.
# ./wifi_signal
Signal level is 217.
# ./wifi_signal
Signal level is 215.
# ./wifi_signal
Signal level is 217.
# ./wifi_signal
Signal level is 217.
Hi! I've run your code in an OpenWRT node successfully

Now, I understand that those values shown on the output are signal strenght but from where or what exactly?

Let me explain my case: I want to get the RSSI values from a client by running a script on an OpenWRT node. I would like to know how to get the RSSI from a specific client.

As far as I know, it's possible by doing: "wl rssi <mac>" but that's not a really good approach, it's not very reliable.

So, how do I get the RSSI value from a specific client?

Thanks.
 
Old 09-08-2011, 11:47 AM   #8
usmanca
LQ Newbie
 
Registered: Sep 2011
Posts: 3

Rep: Reputation: Disabled
Post aztroboy any updates

Hi Aztroboy,
Did you get any success in reading rssi from the client more accurately and reliably ?

usman
 
Old 09-09-2011, 09:13 AM   #9
Bladerunner1989
LQ Newbie
 
Registered: Sep 2011
Posts: 3

Rep: Reputation: Disabled
Hi,
actually I was also struggling with this problem for a while. Specifically speaking in my case I have an ad-hoc network and I want to have a pair RSSI value - MAC-address of the node from whom it was received. But when I run ioctl call in ad-hoc mode it says: "Error performing SIOCGIWSTATS: operation not supported". However, when I run sniffer to see if there are beacons transmitted in the ad-hoc network I see them regularly. So I don't see the reason why it shouldn't work (it works when using infrastructure mode, but this is not what I want). Obviously, using libpcap will provide much more flexible solution, but I want to make sure that there is no solution with ioctl before taking more work.
And by the way, I am using Atheros 5k.
Thanks in advance!
 
Old 09-09-2011, 10:12 AM   #10
usmanca
LQ Newbie
 
Registered: Sep 2011
Posts: 3

Rep: Reputation: Disabled
infrastructure mode

Hi, Could you share your code for infrastructure mode. Are you able to get the RSSI and MAC address pair of the the client nodes ? I am interested in this. Please guide me.

Regards,
 
Old 09-11-2011, 02:23 PM   #11
Bladerunner1989
LQ Newbie
 
Registered: Sep 2011
Posts: 3

Rep: Reputation: Disabled
@usmanca
My code is essentially the same as published by osor. I am not able to get a MAC address corresponding to RSSI value. I didn't find any code of IOCTL command for that. I am switching to libpcap as there are no answers. However in some other forum a person reported that ioctl call worked to report RSSI value for ad-hoc but only on some wireless cards. So I guess it is a question of luck.
Regards.
 
Old 03-27-2012, 11:47 AM   #12
xsguo
LQ Newbie
 
Registered: Mar 2012
Posts: 1

Rep: Reputation: Disabled
I am very interested in this question

Quote:
Originally Posted by usmanca View Post
Hi, Could you share your code for infrastructure mode. Are you able to get the RSSI and MAC address pair of the the client nodes ? I am interested in this. Please guide me.

Regards,
Could you share your code for me, also i want to obtain the RSSI and MAC address pair of the client nodes. Very thanks
 
  


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
How to pass IOCTL arguments from usespace ioctl call devkpict Linux - Kernel 1 12-07-2007 06:45 PM
How can i make centos 4.5's system call using vDSO(call *%gs:0x10) instead of int80 tclwp Red Hat 3 08-06-2007 12:07 AM
Wvdial failing on ioctl call as regular user mugwump84 Linux - Software 3 11-27-2005 01:01 PM
dm driver ioctl call tantrix Programming 0 05-16-2005 06:50 PM
Ioctl() call fails Custer Linux - Wireless Networking 0 02-16-2004 12:47 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking > Linux - Wireless Networking

All times are GMT -5. The time now is 03:20 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