move a few unmaintained packages from trunk to /packages

git-svn-id: svn://svn.openwrt.org/openwrt/packages@33634 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
nbd 2012-10-07 12:50:15 +00:00
parent c4e7d12cfc
commit 27d674c623
220 changed files with 33399 additions and 0 deletions

47
libs/libipfix/Makefile Normal file
View File

@ -0,0 +1,47 @@
#
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=libipfix
PKG_VERSION:=r51
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
PKG_MD5SUM:=0e5b2871ea20ac48eda3f6006c5dba28
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME).$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/libipfix
SECTION:=libs
CATEGORY:=Libraries
TITLE:=IP Flow Information Export Library
URL:=http://www.fokus.fraunhofer.de/de/net/more_about/download/ipfixlib.html
BUILDONLY:=1
endef
TARGET_CFLAGS += \
-ffunction-sections -fdata-sections
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CCOPT="$(TARGET_CFLAGS) -I$(BUILD_DIR)/linux/include" \
prefix="$(PKG_INSTALL_DIR)/usr" \
exec_prefix="$(PKG_INSTALL_DIR)/usr" \
all install
$(TARGET_CROSS)ranlib $(PKG_INSTALL_DIR)/usr/lib/libipfix.a
$(TARGET_CROSS)ranlib $(PKG_INSTALL_DIR)/usr/lib/libipfixmisc.a
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)
$(CP) $(PKG_INSTALL_DIR)/* $(1)/
endef
$(eval $(call BuildPackage,libipfix))

View File

@ -0,0 +1,38 @@
use strict;
my @fields = (
[ "_n", "UINT", " - Number of samples", 4 ],
[ "_s", "UINT", " - Sum of samples", 8 ],
[ "_ss", "UINT", " - Sum of squared samples", 8 ],
);
my $file = $ARGV[0] or die "Syntax: $0 <file> <start>\n";
-f $file or die "File not found\n";
my $start = $ARGV[1];
$start =~ /^\d+$/ or die "Invalid start number";
open FILE, "<$file" or die "Can't open file";
while (<FILE>) {
/^(%?)(\w+),\s*(\w+),\s*(.+)$/ and do {
my $counter = $1;
my $rfield = $2;
my $nfield = $3;
my $descr = $4;
my @f;
if ($counter) {
@f = [ "", "UINT", "", 4];
} else {
@f = @fields;
}
foreach my $f (@f) {
my $nr = $start++;
my $n = $f->[0];
my $N = uc $n;
my $ftype = $f->[1];
my $fdesc = $f->[2];
my $size = $f->[3];
print "$nr, IPFIX_FT_WPROBE_$rfield$N, $size, IPFIX_CODING_$ftype, \"$nfield$n\", \"$descr$fdesc\"\n";
}
};
}
close FILE;

View File

@ -0,0 +1,14 @@
NOISE, global_noise, wprobe global noice floor
PHY_BUSY, global_phy_busy, wprobe global airtime total
PHY_RX, global_phy_rx, wprobe global airtime total from rx-frame
PHY_TX, global_phy_tx, wprobe global airtime total from tx-frame
RSSI, link_rssi, wprobe link received signal strength indication
SIGNAL, link_signal, wprobe link signal strength in dB
IEEE_RX_RATE, link_ieee_rx_rate, wprobe link IEEE 802.11 RX data rate
IEEE_TX_RATE, link_ieee_tx_rate, wprobe link IEEE 802.11 TX data rate
RETRANSMIT_200, link_retransmit_200, wprobe link total retransmissions per packet - <200 bytes
RETRANSMIT_400, link_retransmit_400, wprobe link total retransmissions per packet - <400 bytes
RETRANSMIT_800, link_retransmit_800, wprobe link total retransmissions per packet - <800 bytes
RETRANSMIT_1600, link_retransmit_1600, wprobe link total retransmissions per packet - >800 bytes
%FRAMES, global_frames, wprobe global number of 802.11 frames seen
%PROBEREQ, global_probereq, wprobe global number of 802.11 probe requests seen

View File

@ -0,0 +1,474 @@
--- a/lib/ipfix.c
+++ b/lib/ipfix.c
@@ -37,6 +37,9 @@ $$LIC$$
#ifdef SCTPSUPPORT
#include <netinet/sctp.h>
#endif
+#ifndef NOTHREADS
+#include <pthread.h>
+#endif
#include <fcntl.h>
#include <netdb.h>
@@ -123,6 +126,18 @@ static uint16_t g_lasttid;
static ipfix_datarecord_t g_data = { NULL, NULL, 0 }; /* ipfix_export */
static ipfix_field_t *g_ipfix_fields;
+#ifndef NOTHREADS
+static pthread_mutex_t g_mutex;
+#define mod_lock() { \
+ if ( pthread_mutex_lock( &g_mutex ) !=0 ) \
+ mlogf( 0, "[ipfix] mutex_lock() failed: %s\n", \
+ strerror( errno ) ); \
+ }
+#define mod_unlock() { pthread_mutex_unlock( &g_mutex ); }
+#else
+#define mod_lock()
+#define mod_unlock()
+#endif
/*----- prototypes -------------------------------------------------------*/
@@ -133,6 +148,7 @@ int _ipfix_send_message( ipfix_t *ifh,
ipfix_message_t *message );
int _ipfix_write_msghdr( ipfix_t *ifh, ipfix_message_t *msg, iobuf_t *buf );
void _ipfix_disconnect( ipfix_collector_t *col );
+int _ipfix_export_flush( ipfix_t *ifh );
/* name : do_writeselect
@@ -576,16 +592,18 @@ int ipfix_decode_float( void *in, void *
int ipfix_snprint_float( char *str, size_t size, void *data, size_t len )
{
- float tmp32;
- double tmp64;
+ uint32_t tmp32;
+ uint64_t tmp64;
switch ( len ) {
case 4:
- ipfix_decode_float( data, &tmp32, 4);
- return snprintf( str, size, "%f", tmp32 );
+ memcpy( &tmp32, data, len );
+ tmp32 = htonl( tmp32 );
+ return snprintf( str, size, "%f", (float)tmp32 );
case 8:
- ipfix_decode_float( data, &tmp64, 8);
- return snprintf( str, size, "%lf", tmp64);
+ memcpy( &tmp64, data, len );
+ tmp64 = HTONLL( tmp64 );
+ return snprintf( str, size, "%lf", (double)tmp64 );
default:
break;
}
@@ -682,12 +700,19 @@ int ipfix_get_eno_ieid( char *field, int
* parameters:
* remarks: init module, read field type info.
*/
-int ipfix_init ( void )
+int ipfix_init( void )
{
if ( g_tstart ) {
ipfix_cleanup();
}
+#ifndef NOTHREADS
+ if ( pthread_mutex_init( &g_mutex, NULL ) !=0 ) {
+ mlogf( 0, "[ipfix] pthread_mutex_init() failed: %s\n",
+ strerror(errno) );
+ return -1;
+ }
+#endif
g_tstart = time(NULL);
signal( SIGPIPE, SIG_IGN );
g_lasttid = 255;
@@ -806,6 +831,9 @@ void ipfix_cleanup ( void )
g_data.maxfields = 0;
g_data.lens = NULL;
g_data.addrs = NULL;
+#ifndef NOTHREADS
+ (void)pthread_mutex_destroy( &g_mutex );
+#endif
}
int _ipfix_connect ( ipfix_collector_t *col )
@@ -1465,7 +1493,7 @@ int _ipfix_write_template( ipfix_t
default:
/* check space */
if ( tsize+ifh->offset > IPFIX_DEFAULT_BUFLEN ) {
- if ( ipfix_export_flush( ifh ) < 0 )
+ if ( _ipfix_export_flush( ifh ) < 0 )
return -1;
if ( tsize+ifh->offset > IPFIX_DEFAULT_BUFLEN )
return -1;
@@ -1474,6 +1502,8 @@ int _ipfix_write_template( ipfix_t
/* write template prior to data */
if ( ifh->offset > 0 ) {
memmove( ifh->buffer + tsize, ifh->buffer, ifh->offset );
+ if ( ifh->cs_tid )
+ ifh->cs_header += tsize;
}
buf = ifh->buffer;
@@ -1615,8 +1645,11 @@ int ipfix_open( ipfix_t **ipfixh, int so
return -1;
}
node->ifh = i;
+
+ mod_lock();
node->next = g_ipfixlist;
g_ipfixlist = node;
+ mod_unlock();
*ipfixh = i;
return 0;
@@ -1633,7 +1666,8 @@ void ipfix_close( ipfix_t *h )
{
ipfix_node_t *l, *n;
- ipfix_export_flush( h );
+ mod_lock();
+ _ipfix_export_flush( h );
while( h->collectors )
_ipfix_drop_collector( (ipfix_collector_t**)&h->collectors );
@@ -1659,6 +1693,7 @@ void ipfix_close( ipfix_t *h )
#endif
free(h->buffer);
free(h);
+ mod_unlock();
}
}
@@ -2156,6 +2191,22 @@ void ipfix_release_template( ipfix_t *if
ipfix_delete_template( ifh, templ );
}
+static void _finish_cs( ipfix_t *ifh )
+{
+ size_t buflen;
+ uint8_t *buf;
+
+ /* finish current dataset */
+ if ( (buf=ifh->cs_header) ==NULL )
+ return;
+ buflen = 0;
+ INSERTU16( buf+buflen, buflen, ifh->cs_tid );
+ INSERTU16( buf+buflen, buflen, ifh->cs_bytes );
+ ifh->cs_bytes = 0;
+ ifh->cs_header = NULL;
+ ifh->cs_tid = 0;
+}
+
int ipfix_export( ipfix_t *ifh, ipfix_template_t *templ, ... )
{
int i;
@@ -2199,13 +2250,14 @@ int ipfix_export( ipfix_t *ifh, ipfix_te
g_data.addrs, g_data.lens );
}
-int ipfix_export_array( ipfix_t *ifh,
- ipfix_template_t *templ,
- int nfields,
- void **fields,
- uint16_t *lengths )
+static int
+_ipfix_export_array( ipfix_t *ifh,
+ ipfix_template_t *templ,
+ int nfields,
+ void **fields,
+ uint16_t *lengths )
{
- int i;
+ int i, newset_f=0;
size_t buflen, datasetlen;
uint8_t *p, *buf;
@@ -2249,7 +2301,19 @@ int ipfix_export_array( ipfix_t
/** get size of data set, check space
*/
- for ( i=0, datasetlen=4; i<nfields; i++ ) {
+ if ( templ->tid == ifh->cs_tid ) {
+ newset_f = 0;
+ datasetlen = 0;
+ }
+ else {
+ if ( ifh->cs_tid > 0 ) {
+ _finish_cs( ifh );
+ }
+ newset_f = 1;
+ datasetlen = 4;
+ }
+
+ for ( i=0; i<nfields; i++ ) {
if ( templ->fields[i].flength == IPFIX_FT_VARLEN ) {
if ( lengths[i]>254 )
datasetlen += 3;
@@ -2263,21 +2327,29 @@ int ipfix_export_array( ipfix_t
}
datasetlen += lengths[i];
}
- if ( ((ifh->offset + datasetlen) > IPFIX_DEFAULT_BUFLEN )
- && (ipfix_export_flush( ifh ) <0) ) {
- return -1;
+
+ if ( (ifh->offset + datasetlen) > IPFIX_DEFAULT_BUFLEN ) {
+ if ( ifh->cs_tid )
+ _finish_cs( ifh );
+ newset_f = 1;
+
+ if ( _ipfix_export_flush( ifh ) <0 )
+ return -1;
}
- /* fill buffer
- */
+ /* fill buffer */
buf = (uint8_t*)(ifh->buffer) + ifh->offset;
buflen = 0;
- /* insert data set
- */
- ifh->nrecords ++;
- INSERTU16( buf+buflen, buflen, templ->tid );
- INSERTU16( buf+buflen, buflen, datasetlen );
+ if ( newset_f ) {
+ /* insert data set
+ */
+ ifh->cs_bytes = 0;
+ ifh->cs_header = buf;
+ ifh->cs_tid = templ->tid;
+ INSERTU16( buf+buflen, buflen, templ->tid );
+ INSERTU16( buf+buflen, buflen, 4 );
+ }
/* insert data record
*/
@@ -2303,7 +2375,9 @@ int ipfix_export_array( ipfix_t
buflen += lengths[i];
}
+ ifh->nrecords ++;
ifh->offset += buflen;
+ ifh->cs_bytes += buflen;
if ( ifh->version == IPFIX_VERSION )
ifh->seqno ++;
return 0;
@@ -2313,7 +2387,7 @@ int ipfix_export_array( ipfix_t
* parameters:
* remarks: rewrite this func!
*/
-int ipfix_export_flush( ipfix_t *ifh )
+int _ipfix_export_flush( ipfix_t *ifh )
{
iobuf_t *buf;
ipfix_collector_t *col;
@@ -2322,8 +2396,14 @@ int ipfix_export_flush( ipfix_t *ifh )
if ( (ifh==NULL) || (ifh->offset==0) )
return 0;
- if ( (buf=_ipfix_getbuf()) ==NULL )
+ if ( ifh->cs_tid > 0 ) {
+ /* finish current dataset */
+ _finish_cs( ifh );
+ }
+
+ if ( (buf=_ipfix_getbuf()) ==NULL ) {
return -1;
+ }
#ifdef DEBUG
mlogf( 0, "[ipfix_export_flush] msg has %d records, %d bytes\n",
@@ -2350,3 +2430,30 @@ int ipfix_export_flush( ipfix_t *ifh )
_ipfix_freebuf( buf );
return ret;
}
+
+int ipfix_export_array( ipfix_t *ifh,
+ ipfix_template_t *templ,
+ int nfields,
+ void **fields,
+ uint16_t *lengths )
+{
+ int ret;
+
+ mod_lock();
+ ret = _ipfix_export_array( ifh, templ, nfields, fields, lengths );
+ mod_unlock();
+
+ return ret;
+}
+
+int ipfix_export_flush( ipfix_t *ifh )
+{
+ int ret;
+
+ mod_lock();
+ ret = _ipfix_export_flush( ifh );
+ mod_unlock();
+
+ return ret;
+}
+
--- a/lib/ipfix.h
+++ b/lib/ipfix.h
@@ -142,6 +142,12 @@ typedef struct
int nrecords; /* no. of records in buffer */
size_t offset; /* output buffer fill level */
uint32_t seqno; /* sequence no. of next message */
+
+ /* experimental */
+ int cs_tid; /* template id of current dataset */
+ int cs_bytes; /* size of current set */
+ uint8_t *cs_header; /* start of current set */
+
} ipfix_t;
/** exporter funcs
--- a/lib/ipfix_col.c
+++ b/lib/ipfix_col.c
@@ -897,6 +897,8 @@ int ipfix_decode_datarecord( ipfixt_node
return -1;
}
+ n->ipfixt->fields[i].elem->decode(p,p,len);
+
data->lens[i] = len;
data->addrs[i] = p;
@@ -907,7 +909,7 @@ int ipfix_decode_datarecord( ipfixt_node
return 0;
}
-static void do_free_datarecord( ipfix_datarecord_t *data )
+void ipfix_free_datarecord( ipfix_datarecord_t *data )
{
if ( data ) {
if ( data->addrs )
@@ -925,6 +927,7 @@ int ipfix_parse_msg( ipfix_input_t *inpu
ipfix_hdr_t hdr; /* ipfix packet header */
ipfixs_node_t *s;
ipfix_datarecord_t data = { NULL, NULL, 0 };
+ ipfixe_node_t *e;
uint8_t *buf; /* ipfix payload */
uint16_t setid, setlen; /* set id, set lenght */
int i, nread, offset; /* counter */
@@ -1042,6 +1045,12 @@ int ipfix_parse_msg( ipfix_input_t *inpu
err_flag = 1;
}
else {
+ for ( e=g_exporter; e!=NULL; e=e->next ) {
+ if ( e->elem->export_dset )
+ (void) e->elem->export_dset( t, buf+nread, setlen,
+ e->elem->data );
+ }
+
/** read data records
*/
for ( offset=nread, bytesleft=setlen; bytesleft>4; ) {
@@ -1076,11 +1085,11 @@ int ipfix_parse_msg( ipfix_input_t *inpu
goto errend;
end:
- do_free_datarecord( &data );
+ ipfix_free_datarecord( &data );
return nread;
errend:
- do_free_datarecord( &data );
+ ipfix_free_datarecord( &data );
return -1;
}
@@ -1093,7 +1102,7 @@ void process_client_tcp( int fd, int mas
tcp_conn_t *tcon = (tcp_conn_t*)data;
char *func = "process_client_tcp";
- mlogf( 3, "[%s] fd %d mask %d called.\n", func, fd, mask );
+ mlogf( 4, "[%s] fd %d mask %d called.\n", func, fd, mask );
/** read ipfix header
*/
--- a/lib/ipfix_col.h
+++ b/lib/ipfix_col.h
@@ -88,6 +88,7 @@ typedef struct ipfix_col_info
int (*export_newsource)(ipfixs_node_t*,void*);
int (*export_newmsg)(ipfixs_node_t*,ipfix_hdr_t*,void*);
int (*export_trecord)(ipfixs_node_t*,ipfixt_node_t*,void*);
+ int (*export_dset)(ipfixt_node_t*,uint8_t*,size_t,void*);
int (*export_drecord)(ipfixs_node_t*,ipfixt_node_t*,
ipfix_datarecord_t*,void*);
void (*export_cleanup)(void*);
--- a/lib/ipfix_col_files.c
+++ b/lib/ipfix_col_files.c
@@ -68,7 +68,7 @@ static int export_newsource_file( ipfixs
return -1;
}
snprintf( s->fname+strlen(s->fname), PATH_MAX-strlen(s->fname),
- "/%u", s->odid );
+ "/%u", (unsigned int)s->odid );
if ( (access( s->fname, R_OK ) <0 )
&& (mkdir( s->fname, S_IRWXU ) <0) ) {
mlogf( 0, "[%s] cannot access dir '%s': %s\n",
--- a/lib/ipfix_FOKUS_IEs.txt
+++ b/lib/ipfix_FOKUS_IEs.txt
@@ -24,6 +24,8 @@
196, IPFIX_FT_PKTID, 4, IPFIX_CODING_UINT, "pktId", "FOKUS packet id"
197, IPFIX_FT_STARTTIME, 4, IPFIX_CODING_INT, "startTime", "FOKUS interval start"
198, IPFIX_FT_ENDTIME, 4, IPFIX_CODING_INT, "endTime", "FOKUS interval end"
+199, IPFIX_FT_RTT_USEC, 8, IPFIX_CODING_UINT, "rtt_usec", "FOKUS rtt in us"
+
300, IPFIX_FT_FLOWCREATIONTIMEUSEC, 4, IPFIX_CODING_INT, "flowCreationTimeUsec", "FOKUS flow start usec fraction"
301, IPFIX_FT_FLOWENDTIMEUSEC, 4, IPFIX_CODING_INT, "flowEndTimeUsec", "FOKUS flow end usec fraction"
303, IPFIX_FT_TC_PACKETS, 4, IPFIX_CODING_UINT, "tcPackets", "DAIDALOS Packets seen"
@@ -39,3 +41,48 @@
313, IPFIX_FT_OWDVARMIN_NSEC, 4, IPFIX_CODING_INT, "owdvarmin_nsec", "FOKUS minimum owd variance in ns"
314, IPFIX_FT_OWDVARMAX_NSEC, 4, IPFIX_CODING_INT, "owdvarmax_nsec", "FOKUS maximum ow variance in ns"
+# Project INTERSECTION
+315, IPFIX_FT_SOURCEIPV4FANOUT, 4, IPFIX_CODING_UINT,"sourceIPv4FanOut", "FOKUS IPv4 fanout"
+316, IPFIX_FT_DESTINATIONIPV4FANIN, 4, IPFIX_CODING_UINT,"destinationIPv4FanIn", "FOKUS IPv4 fanin"
+
+# Project PRISM
+
+330, IPFIX_FT_PR_SESSIONID, 4, IPFIX_CODING_UINT, "sessionId", "PRISM Session ID"
+331, IPFIX_FT_PR_TRANSACTIONID, 4, IPFIX_CODING_UINT, "transactionId", "PRISM Transaction ID"
+332, IPFIX_FT_PR_ENCRYPTEDDATA, 65535, IPFIX_CODING_STRING, "encryptedData", "PRISM encrypted data"
+333, IPFIX_FT_PR_DECRYPTIONKEY, 65535, IPFIX_CODING_STRING, "decryptionKey", "PRISM decryption key"
+334, IPFIX_FT_PR_KEYSHARE, 65535, IPFIX_CODING_STRING, "keyShare", "PRISM key share"
+335, IPFIX_FT_PR_KEYSHAREADP, 65535, IPFIX_CODING_STRING, "keyShareAdp", "PRISM key share ADP"
+336, IPFIX_FT_PR_INITVECTOR, 65535, IPFIX_CODING_STRING, "cryptoInitVector", "PRISM crypto init vector"
+
+
+# these information elements have been defined by FOKUS for the Oracle project
+
+402, IPFIX_FT_ORsignalBandwidth, 4, IPFIX_CODING_UINT, "ORsignalBandwidth", "signal bandwidth"
+403, IPFIX_FT_ORsignalPower, 2, IPFIX_CODING_UINT, "ORsignalPower", "ERIP"
+404, IPFIX_FT_ORmodulationType, 2, IPFIX_CODING_UINT, "ORmodulationType", "AM/FM,.."
+405, IPFIX_FT_ORsymbolRate, 2, IPFIX_CODING_UINT, "ORsymbolRate", "symbol rate"
+406, IPFIX_FT_ORmodulationOrder, 1, IPFIX_CODING_UINT, "ORmodulationOrder", "number of levels"
+407, IPFIX_FT_ORrolloffFactor, 2, IPFIX_CODING_UINT, "ORrolloffFactor", "roll of factor"
+408, IPFIX_FT_ORgeopositionLon, 4, IPFIX_CODING_UINT, "ORgeopositionLon", "GPS coordinate, resolution 1 cm"
+409, IPFIX_FT_ORgeopositionLat, 4, IPFIX_CODING_UINT, "ORgeopositionLat", "GPS coordinate, resolution 1 cm"
+410, IPFIX_FT_ORgeopositionElev, 4, IPFIX_CODING_UINT, "ORgeopositionElev", "GPS coordinate, resolution 1 cm"
+411, IPFIX_FT_ORpolicyRecord, 65535, IPFIX_CODING_STRING, "ORpolicyRecord", "policy record has variable length, First 8 bits in data describe the length (in bytes) of the field"
+420, IPFIX_FT_channel_status, 1, IPFIX_CODING_UINT, "channel_status", vacancy of the scanned channel (1: channel busy, 0: channel idle)"
+421, IPFIX_FT_sensing_value, 2, IPFIX_CODING_UINT, "sensing_value", "Cost function output"
+422, IPFIX_FT_sensing_threshold, 2, IPFIX_CODING_UINT, "sensing_threshold", "Decision threshold"
+423, IPFIX_FT_OR_terminal_id, 1, IPFIX_CODING_UINT, "OR_terminal_id", "terminal identifier"
+424, IPFIX_FT_OR_terminal_id_list, 65535, IPFIX_CODING_STRING, "OR_terminal_id_list", "terminal identifier list"
+425, IPFIX_FT_Infrastructure_network_id, 1, IPFIX_CODING_UINT, "Infrastructure_network_id", "network identifier"
+426, IPFIX_FT_Infrastructure_network_type, 1, IPFIX_CODING_UINT, "Infrastructure_network_type", "network type (GSM - 1, UMTS - 2, WiMAX - 3, WiFi - 4)"
+427, IPFIX_FT_Battery_lifetime_min, 1, IPFIX_CODING_UINT, "Battery_lifetime_min", "expected battery lifetime to provide requested services or functionalities, in minutes"
+428, IPFIX_FT_Battery_lifetime_h, 1, IPFIX_CODING_UINT, "Battery_lifetime_h", "expected battery lifetime to provide requested services or functionalities, in hours"
+429, IPFIX_FT_Battery_status, 1, IPFIX_CODING_UINT, "Battery_status", "expected battery lifetime to provide requested services or functionalities, 1 bit status flag, values 1 or 0"
+430, IPFIX_FT_Cell_id_number, 4, IPFIX_CODING_UINT, "Cell_id_number", "16-32 bit cell id number, identifier"
+431, IPFIX_FT_Spectral_allocation_vector, 1, IPFIX_CODING_UINT, "Spectral_allocation_vector", "binary vector to indicate whether a band is free 1 bit 0 or not 1 bit 1"
+432, IPFIX_FT_Spectral_allocation_profile, 2, IPFIX_CODING_UINT, "Spectral_allocation_profile", "received power spectral density vs. frequency to indicate spectral activity in the band of interest (8-16 bits per discrete frequency value)"
+433, IPFIX_FT_Center_frequency, 2, IPFIX_CODING_UINT, "Center_frequency", "Center frequency of the sensed band"
+434, IPFIX_FT_Bandwidth_of_CAP, 2, IPFIX_CODING_UINT, "Bandwidth_of_CAP", "Bandwidth of the spectral allocation profile"
+435, IPFIX_FT_ORmodulation, 1, IPFIX_CODING_UINT, "ORmodulation", "CREST factor"
+436, IPFIX_FT_ORprofileRecord, 65535, IPFIX_CODING_STRING, "ORprofileRecord", "profile record has variable length, First 8 bits in data describe the length (in bytes) of the field"
+

View File

@ -0,0 +1,44 @@
--- a/lib/ipfix_FOKUS_IEs.txt
+++ b/lib/ipfix_FOKUS_IEs.txt
@@ -86,3 +86,41 @@
435, IPFIX_FT_ORmodulation, 1, IPFIX_CODING_UINT, "ORmodulation", "CREST factor"
436, IPFIX_FT_ORprofileRecord, 65535, IPFIX_CODING_STRING, "ORprofileRecord", "profile record has variable length, First 8 bits in data describe the length (in bytes) of the field"
+500, IPFIX_FT_WPROBE_NOISE_N, 4, IPFIX_CODING_UINT, "global_noise_n", "wprobe global noice floor - Number of samples"
+501, IPFIX_FT_WPROBE_NOISE_S, 8, IPFIX_CODING_UINT, "global_noise_s", "wprobe global noice floor - Sum of samples"
+502, IPFIX_FT_WPROBE_NOISE_SS, 8, IPFIX_CODING_UINT, "global_noise_ss", "wprobe global noice floor - Sum of squared samples"
+503, IPFIX_FT_WPROBE_PHY_BUSY_N, 4, IPFIX_CODING_UINT, "global_phy_busy_n", "wprobe global airtime total - Number of samples"
+504, IPFIX_FT_WPROBE_PHY_BUSY_S, 8, IPFIX_CODING_UINT, "global_phy_busy_s", "wprobe global airtime total - Sum of samples"
+505, IPFIX_FT_WPROBE_PHY_BUSY_SS, 8, IPFIX_CODING_UINT, "global_phy_busy_ss", "wprobe global airtime total - Sum of squared samples"
+506, IPFIX_FT_WPROBE_PHY_RX_N, 4, IPFIX_CODING_UINT, "global_phy_rx_n", "wprobe global airtime total from rx-frame - Number of samples"
+507, IPFIX_FT_WPROBE_PHY_RX_S, 8, IPFIX_CODING_UINT, "global_phy_rx_s", "wprobe global airtime total from rx-frame - Sum of samples"
+508, IPFIX_FT_WPROBE_PHY_RX_SS, 8, IPFIX_CODING_UINT, "global_phy_rx_ss", "wprobe global airtime total from rx-frame - Sum of squared samples"
+509, IPFIX_FT_WPROBE_PHY_TX_N, 4, IPFIX_CODING_UINT, "global_phy_tx_n", "wprobe global airtime total from tx-frame - Number of samples"
+510, IPFIX_FT_WPROBE_PHY_TX_S, 8, IPFIX_CODING_UINT, "global_phy_tx_s", "wprobe global airtime total from tx-frame - Sum of samples"
+511, IPFIX_FT_WPROBE_PHY_TX_SS, 8, IPFIX_CODING_UINT, "global_phy_tx_ss", "wprobe global airtime total from tx-frame - Sum of squared samples"
+512, IPFIX_FT_WPROBE_RSSI_N, 4, IPFIX_CODING_UINT, "link_rssi_n", "wprobe link received signal strength indication - Number of samples"
+513, IPFIX_FT_WPROBE_RSSI_S, 8, IPFIX_CODING_UINT, "link_rssi_s", "wprobe link received signal strength indication - Sum of samples"
+514, IPFIX_FT_WPROBE_RSSI_SS, 8, IPFIX_CODING_UINT, "link_rssi_ss", "wprobe link received signal strength indication - Sum of squared samples"
+515, IPFIX_FT_WPROBE_SIGNAL_N, 4, IPFIX_CODING_UINT, "link_signal_n", "wprobe link signal strength in dB - Number of samples"
+516, IPFIX_FT_WPROBE_SIGNAL_S, 8, IPFIX_CODING_UINT, "link_signal_s", "wprobe link signal strength in dB - Sum of samples"
+517, IPFIX_FT_WPROBE_SIGNAL_SS, 8, IPFIX_CODING_UINT, "link_signal_ss", "wprobe link signal strength in dB - Sum of squared samples"
+518, IPFIX_FT_WPROBE_IEEE_RX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_rx_rate_n", "wprobe link IEEE 802.11 RX data rate - Number of samples"
+519, IPFIX_FT_WPROBE_IEEE_RX_RATE_S, 8, IPFIX_CODING_UINT, "link_ieee_rx_rate_s", "wprobe link IEEE 802.11 RX data rate - Sum of samples"
+520, IPFIX_FT_WPROBE_IEEE_RX_RATE_SS, 8, IPFIX_CODING_UINT, "link_ieee_rx_rate_ss", "wprobe link IEEE 802.11 RX data rate - Sum of squared samples"
+521, IPFIX_FT_WPROBE_IEEE_TX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_tx_rate_n", "wprobe link IEEE 802.11 TX data rate - Number of samples"
+522, IPFIX_FT_WPROBE_IEEE_TX_RATE_S, 8, IPFIX_CODING_UINT, "link_ieee_tx_rate_s", "wprobe link IEEE 802.11 TX data rate - Sum of samples"
+523, IPFIX_FT_WPROBE_IEEE_TX_RATE_SS, 8, IPFIX_CODING_UINT, "link_ieee_tx_rate_ss", "wprobe link IEEE 802.11 TX data rate - Sum of squared samples"
+524, IPFIX_FT_WPROBE_RETRANSMIT_200_N, 4, IPFIX_CODING_UINT, "link_retransmit_200_n", "wprobe link total retransmissions per packet - <200 bytes - Number of samples"
+525, IPFIX_FT_WPROBE_RETRANSMIT_200_S, 8, IPFIX_CODING_UINT, "link_retransmit_200_s", "wprobe link total retransmissions per packet - <200 bytes - Sum of samples"
+526, IPFIX_FT_WPROBE_RETRANSMIT_200_SS, 8, IPFIX_CODING_UINT, "link_retransmit_200_ss", "wprobe link total retransmissions per packet - <200 bytes - Sum of squared samples"
+527, IPFIX_FT_WPROBE_RETRANSMIT_400_N, 4, IPFIX_CODING_UINT, "link_retransmit_400_n", "wprobe link total retransmissions per packet - <400 bytes - Number of samples"
+528, IPFIX_FT_WPROBE_RETRANSMIT_400_S, 8, IPFIX_CODING_UINT, "link_retransmit_400_s", "wprobe link total retransmissions per packet - <400 bytes - Sum of samples"
+529, IPFIX_FT_WPROBE_RETRANSMIT_400_SS, 8, IPFIX_CODING_UINT, "link_retransmit_400_ss", "wprobe link total retransmissions per packet - <400 bytes - Sum of squared samples"
+530, IPFIX_FT_WPROBE_RETRANSMIT_800_N, 4, IPFIX_CODING_UINT, "link_retransmit_800_n", "wprobe link total retransmissions per packet - <800 bytes - Number of samples"
+531, IPFIX_FT_WPROBE_RETRANSMIT_800_S, 8, IPFIX_CODING_UINT, "link_retransmit_800_s", "wprobe link total retransmissions per packet - <800 bytes - Sum of samples"
+532, IPFIX_FT_WPROBE_RETRANSMIT_800_SS, 8, IPFIX_CODING_UINT, "link_retransmit_800_ss", "wprobe link total retransmissions per packet - <800 bytes - Sum of squared samples"
+533, IPFIX_FT_WPROBE_RETRANSMIT_1600_N, 4, IPFIX_CODING_UINT, "link_retransmit_1600_n", "wprobe link total retransmissions per packet - >800 bytes - Number of samples"
+534, IPFIX_FT_WPROBE_RETRANSMIT_1600_S, 8, IPFIX_CODING_UINT, "link_retransmit_1600_s", "wprobe link total retransmissions per packet - >800 bytes - Sum of samples"
+535, IPFIX_FT_WPROBE_RETRANSMIT_1600_SS, 8, IPFIX_CODING_UINT, "link_retransmit_1600_ss", "wprobe link total retransmissions per packet - >800 bytes - Sum of squared samples"
+536, IPFIX_FT_WPROBE_FRAMES, 4, IPFIX_CODING_UINT, "global_frames", "wprobe global number of 802.11 frames seen"
+537, IPFIX_FT_WPROBE_PROBEREQ, 4, IPFIX_CODING_UINT, "global_probereq", "wprobe global number of 802.11 probe requests seen"

View File

@ -0,0 +1,27 @@
Index: libipfix.r51/lib/Makefile.in
===================================================================
--- libipfix.r51.orig/lib/Makefile.in 2008-08-05 15:15:23.000000000 +0200
+++ libipfix.r51/lib/Makefile.in 2012-06-05 19:26:34.061692890 +0200
@@ -41,7 +41,7 @@
INCLS = -I. -I..
CFLAGS = $(CCOPT) $(INCLS) $(DEFS)
-TARGETS = libmisc.a libipfix.a
+TARGETS = libipfixmisc.a libipfix.a
OBJS = ipfix.o ipfix_col.o ipfix_print.o \
ipfix_col_files.o ipfix_col_db.o @IPFIX_DB_OBJ@ @IPFIX_SSL_OBJ@
DEPHDR = ipfix.h ipfix_def.h ipfix_fields.h ipfix_def_fokus.h ipfix_fields_fokus.h
@@ -60,11 +60,11 @@
install:
@[ -d ${libdir} ] || (mkdir -p ${libdir}; chmod 755 ${libdir})
$(INSTALL_DATA) libipfix.a ${libdir}/
- $(INSTALL_DATA) libmisc.a ${libdir}/
+ $(INSTALL_DATA) libipfixmisc.a ${libdir}/
@[ -d ${includedir} ] || (mkdir -p ${includedir}; chmod 755 ${includedir})
$(INSTALL_HEADER) ipfix*.h mlog.h mpoll.h ${includedir}/
-libmisc.a: $(MISCOBJS) Makefile
+libipfixmisc.a: $(MISCOBJS) Makefile
@rm -f $@
$(AR) rc $@ $(MISCOBJS)

51
net/bridge-utils/Makefile Normal file
View File

@ -0,0 +1,51 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=bridge-utils
PKG_RELEASE:=1
PKG_SOURCE_URL:=@SF/bridge
PKG_VERSION:=1.5
PKG_MD5SUM:=ec7b381160b340648dede58c31bb2238
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
include $(INCLUDE_DIR)/package.mk
define Package/bridge
SECTION:=net
CATEGORY:=Base system
TITLE:=Ethernet bridging configuration utility
URL:=http://bridge.sourceforge.net/
endef
define Package/bridge/description
Manage ethernet bridging: a way to connect networks together to
form a larger network.
endef
CONFIGURE_ARGS += \
--with-linux-headers="$(LINUX_DIR)" \
define Build/Prepare
$(call Build/Prepare/Default)
( cd $(PKG_BUILD_DIR) ; \
[ -f ./configure ] || { \
ln -sf configure.in configure.ac ; \
autoconf ; \
} \
)
endef
define Package/bridge/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/brctl/brctl $(1)/usr/sbin
endef
$(eval $(call BuildPackage,bridge))

View File

@ -0,0 +1,11 @@
--- a/libbridge/Makefile.in
+++ b/libbridge/Makefile.in
@@ -5,7 +5,7 @@ AR=ar
RANLIB=@RANLIB@
CC=@CC@
-CFLAGS = -Wall -g $(KERNEL_HEADERS)
+CFLAGS = -Wall -g @CFLAGS@ $(KERNEL_HEADERS)
prefix=@prefix@
exec_prefix=@exec_prefix@

74
net/crda/Makefile Normal file
View File

@ -0,0 +1,74 @@
#
# Copyright (C) 2009-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=crda
PKG_RELEASE:=1
PKG_VERSION:=1.1.2
PKG_SOURCE_URL:=http://wireless.kernel.org/download/crda
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_MD5SUM:=5226f65aebacf94baaf820f8b4e06df4
PKG_REGULATORY_NAME:=regulatory
PKG_REGULATORY_VERSION:=2011.04.28
PKG_REGULATORY_SOURCE_URL:=http://wireless.kernel.org/download/wireless-regdb/regulatory.bins
PKG_REGULATORY_SOURCE:=$(PKG_REGULATORY_VERSION)-$(PKG_REGULATORY_NAME).bin
PKG_REGULATORY_MD5SUM:=1535e98bcaba732e2f8e8f62dac6f369
include $(INCLUDE_DIR)/package.mk
define Package/crda
SECTION:=net
CATEGORY:=Network
TITLE:=Central Regulatory Domain Agent (CRDA)
DEPENDS:=+libnl-tiny
URL:=http://wireless.kernel.org/en/developers/Regulatory/CRDA
endef
define Download/wireless-regdb
FILE:=$(PKG_REGULATORY_SOURCE)
URL:=$(PKG_REGULATORY_SOURCE_URL)
VERSION:=$(PKG_REGULATORY_VERSION)
MD5SUM:=$(PKG_REGULATORY_MD5SUM)
endef
$(eval $(call Download,wireless-regdb))
define Package/crda/description
This is the Central Regulatory Domain Agent for Linux. It serves one
purpose: tell Linux kernel what to enforce. In essence it is a udev
helper for communication between the kernel and userspace. You only
need to run this manually for debugging purposes. For manual changing
of regulatory domains use iw (iw reg set) or wpa_supplicant (feature
yet to be added).
endef
TARGET_CPPFLAGS := \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-D_GNU_SOURCE \
$(TARGET_CPPFLAGS)
MAKE_FLAGS += \
NL1FOUND="" NL2FOUND=Y \
NLLIBNAME="libnl-tiny" \
NLLIBS="-lnl-tiny -lm" \
REG_BIN="$(DL_DIR)/$(PKG_REGULATORY_SOURCE)" \
crda
define Package/crda/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_DIR) $(1)/etc/hotplug.d
$(INSTALL_DIR) $(1)/etc/hotplug.d/platform
$(INSTALL_DIR) $(1)/usr/lib/crda
$(INSTALL_BIN) $(PKG_BUILD_DIR)/crda $(1)/sbin/
$(INSTALL_DATA) ./files/hotplug.rule $(1)/etc/hotplug.d/platform/10-regulatory
$(INSTALL_DATA) $(DL_DIR)/$(PKG_REGULATORY_SOURCE) $(1)/usr/lib/crda/regulatory.bin
endef
$(eval $(call BuildPackage,crda))

View File

@ -0,0 +1,6 @@
#!/bin/sh
# Copyright (C) 2009 OpenWrt.org
[ change = "$ACTION" -a regulatory.0 = "$DEVICENAME" ] && {
/sbin/crda
}

View File

@ -0,0 +1,13 @@
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,9 @@ LDLIBS += `pkg-config --libs openssl`
reglib.o: keys-ssl.c
-else
+endif
+
+ifeq ($(USE_GCRYPT),1)
CFLAGS += -DUSE_GCRYPT
LDLIBS += -lgcrypt

55
net/madwifi/Config.in Normal file
View File

@ -0,0 +1,55 @@
menu "Configuration"
depends on PACKAGE_kmod-madwifi
config MADWIFI_DEBUG
bool "Enable compilation of debugging features"
depends on DEVEL
default n
config MADWIFI_COMPRESSION
bool "Enable Atheros Super A/G Compression"
depends !TARGET_ar71xx
default n
help
Enables Atheros Super A/G Hardware Compression Engine.
config MADWIFI_SINGLE_MODULE
bool "Combine driver and net80211 into a single module"
default y
help
This option combines all driver and stack related code (except for HAL)
into a single module, thus saving space and removing unnecessary kernel
exports
choice
prompt "Rate control algorithm selection"
default MADWIFI_RCA_MINSTREL
help
This option controls how MadWifi chooses its bitrate.
config MADWIFI_RCA_MINSTREL
bool "Use the Minstrel rate control algorithm"
help
This code is takes a wandering minstrel approach. Wander around the
different rates, singing wherever you can. And then, look at the
performance, and make a choice. Note that the wandering minstrel will
always wander in directions where he/she feels he/she will get paid
the best for his/her work.
config MADWIFI_RCA_SAMPLERATE
bool "Use the SampleRate rate control algorithm"
help
SampleRate decides on the transmission bit-rate based on the past
history of performance; it keeps a record of the number of successive
failures, the number of successful transmits and the total transmission
time along with the destination for that bit-rate. Stale samples are
removed based on a EWMA windowing mechanism. If in the sampling
process, no successful acknowledgment is received or the number of
packets sent is multiple of 10 on a specific link, it transmits the
packet with the highest rate which has not failed 4 successive times.
Other than that it transmits packets at the rate which has the lowest
average transmission time.
endchoice
endmenu

266
net/madwifi/Makefile Normal file
View File

@ -0,0 +1,266 @@
#
# Copyright (C) 2006-2009 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=madwifi
PKG_REV:=3314
PKG_VERSION:=r$(PKG_REV)
PKG_RELEASE:=6
PKG_SOURCE_PROTO:=svn
PKG_SOURCE_VERSION:=$(PKG_REV)
PKG_SOURCE_SUBDIR:=$(if $(PKG_BRANCH),$(PKG_BRANCH),madwifi-trunk)-$(PKG_VERSION)
PKG_SOURCE_URL:=http://madwifi-project.org/svn/madwifi/$(if $(PKG_BRANCH),branches/$(PKG_BRANCH),trunk)
PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
PKG_MIRROR_MD5SUM:=086b026d1c1561be8a949b79b0931404
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(PKG_BRANCH),$(PKG_BRANCH),madwifi-trunk)-$(PKG_VERSION)
HAL_VERSION:=20090508
HAL_FILE:=ath_hal-$(HAL_VERSION).tgz
HAL_MD5SUM:=4ab7ae8bdb96c0be388c98bf8f92d5ca
PKG_BUILD_DEPENDS:=wprobe
include $(INCLUDE_DIR)/package.mk
ifdef CONFIG_MADWIFI_COMPRESSION
COMPRESSION:=1
else
COMPRESSION:=0
endif
define Download/hal
FILE:=$(HAL_FILE)
URL:=http://mirror2.openwrt.org/sources
MD5SUM:=$(HAL_MD5SUM)
endef
$(eval $(call Download,hal))
ifneq ($(CONFIG_TARGET_atheros),)
BUS:=AHB
else
ifneq ($(CONFIG_PCI_SUPPORT),)
BUS:=PCI
endif
endif
ifneq ($(CONFIG_CPU_MIPS32_R2),)
ifeq ($(ARCH),mips)
HAL_TARGET:=mips32r2-be-elf
endif
ifeq ($(ARCH),mipsel)
HAL_TARGET:=mips32r2-le-elf
endif
else
ifeq ($(ARCH),mips)
HAL_TARGET:=mips32-be-elf
endif
ifeq ($(ARCH),mipsel)
HAL_TARGET:=mips32-le-elf
endif
endif
ifeq ($(ARCH),i386)
HAL_TARGET:=i386-elf
endif
ifeq ($(ARCH),i686)
HAL_TARGET:=i386-elf
endif
ifeq ($(ARCH),armeb)
HAL_TARGET:=xscale-be-elfgnueabi
endif
ifeq ($(ARCH),arm)
HAL_TARGET:=xscale-le-elfgnueabi
ifeq ($(BOARD),cns21xx)
HAL_TARGET:=armv4-le-elfgnueabi
endif
ifeq ($(BOARD),cns3xxx)
HAL_TARGET:=arm11-le-elfgnueabi
endif
ifeq ($(BOARD),gemini)
HAL_TARGET:=armv4-le-elfgnueabi
endif
endif
ifeq ($(ARCH),powerpc)
HAL_TARGET:=powerpc-be-elf
endif
ifneq ($(CONFIG_TARGET_atheros),)
HAL_TARGET:=wisoc
endif
ifdef CONFIG_MADWIFI_RCA_MINSTREL
RATE_CONTROL:=minstrel
endif
ifdef CONFIG_MADWIFI_RCA_ONOE
RATE_CONTROL:=onoe
endif
ifdef CONFIG_MADWIFI_RCA_AMRR
RATE_CONTROL:=amrr
endif
ifdef CONFIG_MADWIFI_RCA_SAMPLERATE
RATE_CONTROL:=sample
endif
ifneq ($(CONFIG_MADWIFI_SINGLE_MODULE),)
MADWIFI_FILES:= $(PKG_BUILD_DIR)/ath_hal/ath_hal.ko
else
MADWIFI_FILES:= \
$(PKG_BUILD_DIR)/net80211/wlan.ko \
$(PKG_BUILD_DIR)/net80211/wlan_scan_ap.ko \
$(PKG_BUILD_DIR)/net80211/wlan_scan_sta.ko \
$(PKG_BUILD_DIR)/ath_hal/ath_hal.ko \
$(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).ko \
$(PKG_BUILD_DIR)/net80211/wlan_acl.ko \
$(PKG_BUILD_DIR)/net80211/wlan_ccmp.ko \
$(PKG_BUILD_DIR)/net80211/wlan_tkip.ko \
$(PKG_BUILD_DIR)/net80211/wlan_wep.ko \
$(PKG_BUILD_DIR)/net80211/wlan_xauth.ko
endif
ifneq ($(CONFIG_MADWIFI_SINGLE_MODULE),)
MADWIFI_AUTOLOAD:= ath_hal
else
MADWIFI_AUTOLOAD:= \
wlan \
wlan_scan_ap \
wlan_scan_sta \
ath_hal \
ath_rate_$(RATE_CONTROL) \
wlan_acl \
wlan_ccmp \
wlan_tkip \
wlan_wep \
wlan_xauth
endif
ifeq ($(findstring AHB,$(BUS)),AHB)
MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_ahb.ko
MADWIFI_AUTOLOAD+= ath_ahb
endif
ifeq ($(findstring PCI,$(BUS)),PCI)
MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_pci.ko
MADWIFI_AUTOLOAD+= ath_pci
endif
MADWIFI_APPLETS:=80211stats athchans athkey athstats wlanconfig ath_info madwifi_multi
ifdef CONFIG_MADWIFI_DEBUG
MADWIFI_APPLETS += athdebug 80211debug
endif
define KernelPackage/madwifi
SUBMENU:=Wireless Drivers
TITLE:=Driver for Atheros wireless chipsets
URL:=http://madwifi-project.org/
DEPENDS:=+wireless-tools @PCI_SUPPORT @(!(TARGET_avr32||TARGET_cobalt||TARGET_ep93xx||TARGET_etrax||TARGET_octeon||TARGET_pxcab||TARGET_sibyte)||BROKEN) +@DRIVER_WEXT_SUPPORT
FILES:=$(MADWIFI_FILES)
AUTOLOAD:=$(call AutoLoad,50,$(MADWIFI_AUTOLOAD))
MENU:=1
endef
define KernelPackage/madwifi/description
This package contains a driver for Atheros 802.11a/b/g chipsets.
endef
define KernelPackage/madwifi/config
source "$(SOURCE)/Config.in"
endef
MADWIFI_INC = \
-I$(PKG_BUILD_DIR) \
-I$(PKG_BUILD_DIR)/include \
-I$(PKG_BUILD_DIR)/hal \
-I$(PKG_BUILD_DIR)/ath \
-I$(PKG_BUILD_DIR)/ath_hal \
-I$(PKG_BUILD_DIR)/net80211 \
-I$(STAGING_DIR)/usr/include/wprobe \
-include $(PKG_BUILD_DIR)/include/compat.h
MAKE_ARGS:= \
PATH="$(TARGET_PATH)" \
ARCH="$(LINUX_KARCH)" \
ARCH-y="$(LINUX_KARCH)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
TARGET="$(HAL_TARGET)" \
TOOLPREFIX="$(KERNEL_CROSS)" \
TOOLPATH="$(KERNEL_CROSS)" \
KERNELPATH="$(LINUX_DIR)" \
LDOPTS="--no-warn-mismatch " \
ATH_RATE="$(RATE_CONTROL)" \
ATH_CAP_SUPERG_COMP="$(COMPRESSION)" \
DO_MULTI=1 \
SINGLE_MODULE=$(if $(CONFIG_MADWIFI_SINGLE_MODULE),1) \
INCS="$(MADWIFI_INC)" \
$(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
MAKE_VARS:= \
COPTS="-DATH_REVERSE_ENGINEERING=1" \
define Build/Prepare/HAL
rm -rf $(PKG_BUILD_DIR)/tmp
mkdir -p $(PKG_BUILD_DIR)/tmp
tar xvzf $(DL_DIR)/$(HAL_FILE) -C $(PKG_BUILD_DIR)/tmp
$(CP) $(PKG_BUILD_DIR)/tmp/ath_hal*/* $(PKG_BUILD_DIR)/hal/
rm -rf $(PKG_BUILD_DIR)/tmp
endef
define Build/Prepare
$(call Build/Prepare/Default)
$(call Build/Prepare/HAL)
# patch cflags
$(SED) 's, -E[LB],,' \
-e 's, -mips2,,' \
-e 's, -mapcs-32,,' \
-e 's, -mlong-calls,,' \
$(PKG_BUILD_DIR)/hal/public/*.inc
$(SED) 's,march=armv4,march=armv5te,' \
$(PKG_BUILD_DIR)/hal/public/xscale*.inc
endef
ifeq ($(findstring AHB,$(BUS)),AHB)
define Build/Compile/ahb
$(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) BUS="AHB" modules
$(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) CFLAGS="$(TARGET_CFLAGS)" tools
endef
endif
ifeq ($(findstring PCI,$(BUS)),PCI)
define Build/Compile/pci
$(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) BUS="PCI" modules
$(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_ARGS) CFLAGS="$(TARGET_CFLAGS)" tools
endef
endif
define Build/Configure
$(SED) 's,-E[LB] ,,g' $(PKG_BUILD_DIR)/hal/public/*.inc
endef
define Build/Compile
$(call Build/Compile/ahb)
$(call Build/Compile/pci)
endef
define Build/InstallDev
mkdir -p $(1)/usr/include/madwifi
$(CP) $(PKG_BUILD_DIR)/include $(1)/usr/include/madwifi/
mkdir -p $(1)/usr/include/madwifi/net80211
$(CP) $(PKG_BUILD_DIR)/net80211/*.h $(1)/usr/include/madwifi/net80211/
endef
define KernelPackage/madwifi/install
$(INSTALL_DIR) $(1)/usr/sbin
$(CP) ./files/* $(1)/
$(CP) $(foreach applet,$(MADWIFI_APPLETS),$(PKG_BUILD_DIR)/tools/$(applet)) $(1)/usr/sbin/
endef
$(eval $(call KernelPackage,madwifi))

View File

@ -0,0 +1,12 @@
if [ "$ACTION" = "add" -o "$ACTION" = "register" ]; then
case "$INTERFACE" in
ath*.sta*)
local BASEIF="${INTERFACE%%\.*}"
include /lib/network
scan_interfaces
local CONFIG="$(find_config "$BASEIF")"
[ -n "$CONFIG" ] && setup_interface "$INTERFACE" "$CONFIG"
;;
esac
fi

View File

@ -0,0 +1,498 @@
#!/bin/sh
append DRIVERS "atheros"
find_atheros_phy() {
local device="$1"
local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
config_get phy "$device" phy
[ -z "$phy" -a -n "$macaddr" ] && {
cd /proc/sys/dev
for phy in $(ls -d wifi* 2>&-); do
[ "$macaddr" = "$(cat /sys/class/net/${phy}/address)" ] || continue
config_set "$device" phy "$phy"
break
done
config_get phy "$device" phy
}
[ -n "$phy" -a -d "/proc/sys/dev/$phy" ] || {
echo "phy for wifi device $1 not found"
return 1
}
[ -z "$macaddr" ] && {
config_set "$device" macaddr "$(cat /sys/class/net/${phy}/address)"
}
return 0
}
scan_atheros() {
local device="$1"
local wds
local adhoc ahdemo sta ap monitor disabled
[ ${device%[0-9]} = "wifi" ] && config_set "$device" phy "$device"
local ifidx=0
config_get vifs "$device" vifs
for vif in $vifs; do
config_get_bool disabled "$vif" disabled 0
[ $disabled = 0 ] || continue
local vifname
[ $ifidx -gt 0 ] && vifname="ath${device#radio}-$ifidx" || vifname="ath${device#radio}"
config_get ifname "$vif" ifname
config_set "$vif" ifname "${ifname:-$vifname}"
config_get mode "$vif" mode
case "$mode" in
adhoc|ahdemo|sta|ap|monitor)
append $mode "$vif"
;;
wds)
config_get ssid "$vif" ssid
[ -z "$ssid" ] && continue
config_set "$vif" wds 1
config_set "$vif" mode sta
mode="sta"
addr="$ssid"
${addr:+append $mode "$vif"}
;;
*) echo "$device($vif): Invalid mode, ignored."; continue;;
esac
ifidx=$(($ifidx + 1))
done
case "${adhoc:+1}:${sta:+1}:${ap:+1}" in
# valid mode combinations
1::) wds="";;
1::1);;
:1:1)config_set "$device" nosbeacon 1;; # AP+STA, can't use beacon timers for STA
:1:);;
::1);;
::);;
*) echo "$device: Invalid mode combination in config"; return 1;;
esac
config_set "$device" vifs "${sta:+$sta }${ap:+$ap }${adhoc:+$adhoc }${ahdemo:+$ahdemo }${wds:+$wds }${monitor:+$monitor}"
}
disable_atheros() (
local device="$1"
find_atheros_phy "$device" || return 0
config_get phy "$device" phy
set_wifi_down "$device"
include /lib/network
cd /proc/sys/net
for dev in *; do
grep "$phy" "$dev/%parent" >/dev/null 2>/dev/null && {
[ -f "/var/run/wifi-${dev}.pid" ] &&
kill "$(cat "/var/run/wifi-${dev}.pid")"
ifconfig "$dev" down
unbridge "$dev"
wlanconfig "$dev" destroy
}
done
return 0
)
enable_atheros() {
local device="$1"
find_atheros_phy "$device" || return 0
config_get phy "$device" phy
config_get regdomain "$device" regdomain
[ -n "$regdomain" ] && echo "$regdomain" > /proc/sys/dev/$phy/regdomain
config_get country "$device" country
case "$country" in
[A-Za-z]*) country=`grep -i "$country" /lib/wifi/madwifi_countrycodes.txt |cut -d " " -f 2`;;
[0-9]*) ;;
*) country="" ;;
esac
[ -n "$country" ] && echo "$country" > /proc/sys/dev/$phy/countrycode
config_get_bool outdoor "$device" outdoor "0"
echo "$outdoor" > /proc/sys/dev/$phy/outdoor
config_get channel "$device" channel
config_get vifs "$device" vifs
config_get txpower "$device" txpower
[ auto = "$channel" ] && channel=0
config_get_bool antdiv "$device" diversity
config_get antrx "$device" rxantenna
config_get anttx "$device" txantenna
config_get_bool softled "$device" softled
config_get antenna "$device" antenna
devname="$(cat /proc/sys/dev/$phy/dev_name)"
local antgpio=
local invert=
case "$devname" in
NanoStation2) antgpio=7; invert=1;;
NanoStation5) antgpio=1; invert=1;;
"NanoStation Loco2") antgpio=2;;
"NanoStation Loco5")
case "$antenna" in
horizontal) antdiv=0; anttx=1; antrx=1;;
vertical) antdiv=0; anttx=2; antrx=2;;
*) antdiv=1; anttx=0; antrx=0;;
esac
;;
esac
if [ -n "$invert" ]; then
_set="clear"
_clear="set"
else
_set="set"
_clear="clear"
fi
if [ -n "$antgpio" ]; then
softled=0
case "$devname" in
"NanoStation Loco2")
antdiv=0
antrx=1
anttx=1
case "$antenna" in
horizontal) gpioval=0;;
*) gpioval=1;;
esac
;;
*)
case "$antenna" in
external) antdiv=0; antrx=1; anttx=1; gpioval=1;;
horizontal) antdiv=0; antrx=1; anttx=1; gpioval=0;;
vertical) antdiv=0; antrx=2; anttx=2; gpioval=0;;
auto) antdiv=1; antrx=0; anttx=0; gpioval=0;;
esac
;;
esac
[ -x "$(which gpioctl 2>/dev/null)" ] || antenna=
gpioctl "dirout" "$antgpio" >/dev/null 2>&1
case "$gpioval" in
0)
gpioctl "$_clear" "$antgpio" >/dev/null 2>&1
;;
1)
gpioctl "$_set" "$antgpio" >/dev/null 2>&1
;;
esac
fi
[ -n "$antdiv" ] && sysctl -w dev."$phy".diversity="$antdiv" >&-
[ -n "$antrx" ] && sysctl -w dev."$phy".rxantenna="$antrx" >&-
[ -n "$anttx" ] && sysctl -w dev."$phy".txantenna="$anttx" >&-
[ -n "$softled" ] && sysctl -w dev."$phy".softled="$softled" >&-
config_get distance "$device" distance
[ -n "$distance" ] && sysctl -w dev."$phy".distance="$distance" >&-
for vif in $vifs; do
local start_hostapd= vif_txpower= nosbeacon=
config_get ifname "$vif" ifname
config_get enc "$vif" encryption
config_get eap_type "$vif" eap_type
config_get mode "$vif" mode
case "$mode" in
sta) config_get_bool nosbeacon "$device" nosbeacon;;
adhoc) config_get_bool nosbeacon "$vif" sw_merge 1;;
esac
[ "$nosbeacon" = 1 ] || nosbeacon=""
ifname=$(wlanconfig "$ifname" create nounit wlandev "$phy" wlanmode "$mode" ${nosbeacon:+nosbeacon})
[ $? -ne 0 ] && {
echo "enable_atheros($device): Failed to set up $mode vif $ifname" >&2
continue
}
config_set "$vif" ifname "$ifname"
config_get hwmode "$device" hwmode
[ -z "$hwmode" ] && config_get hwmode "$device" mode
pureg=0
case "$hwmode" in
*b) hwmode=11b;;
*bg) hwmode=11g;;
*g) hwmode=11g; pureg=1;;
*gdt) hwmode=11gdt;;
*a) hwmode=11a;;
*adt) hwmode=11adt;;
*ast) hwmode=11ast;;
*fh) hwmode=fh;;
*) hwmode=auto;;
esac
iwpriv "$ifname" mode "$hwmode"
iwpriv "$ifname" pureg "$pureg"
iwconfig "$ifname" channel "$channel" >/dev/null 2>/dev/null
config_get_bool hidden "$vif" hidden 0
iwpriv "$ifname" hide_ssid "$hidden"
config_get ff "$vif" ff
if [ -n "$ff" ]; then
iwpriv "$ifname" ff "$ff"
fi
config_get wds "$vif" wds
case "$wds" in
1|on|enabled) wds=1;;
*) wds=0;;
esac
iwpriv "$ifname" wds "$wds" >/dev/null 2>&1
[ "$mode" = ap -a "$wds" = 1 ] && {
config_get_bool wdssep "$vif" wdssep 1
[ -n "$wdssep" ] && iwpriv "$ifname" wdssep "$wdssep"
}
case "$enc" in
wep*)
case "$enc" in
*shared*) iwpriv "$ifname" authmode 2;;
*) iwpriv "$ifname" authmode 1;;
esac
for idx in 1 2 3 4; do
config_get key "$vif" "key${idx}"
iwconfig "$ifname" enc "[$idx]" "${key:-off}"
done
config_get key "$vif" key
key="${key:-1}"
case "$key" in
[1234]) iwconfig "$ifname" enc "[$key]";;
*) iwconfig "$ifname" enc "$key";;
esac
;;
psk*|wpa*)
start_hostapd=1
config_get key "$vif" key
;;
esac
case "$mode" in
sta|adhoc|ahdemo)
config_get addr "$vif" bssid
[ -z "$addr" ] || {
iwconfig "$ifname" ap "$addr"
}
;;
esac
config_get_bool uapsd "$vif" uapsd 0
iwpriv "$ifname" uapsd "$uapsd"
config_get_bool bgscan "$vif" bgscan
[ -n "$bgscan" ] && iwpriv "$ifname" bgscan "$bgscan"
config_get rate "$vif" rate
[ -n "$rate" ] && iwconfig "$ifname" rate "${rate%%.*}"
config_get mcast_rate "$vif" mcast_rate
[ -n "$mcast_rate" ] && iwpriv "$ifname" mcast_rate "${mcast_rate%%.*}"
config_get frag "$vif" frag
[ -n "$frag" ] && iwconfig "$ifname" frag "${frag%%.*}"
config_get rts "$vif" rts
[ -n "$rts" ] && iwconfig "$ifname" rts "${rts%%.*}"
config_get_bool comp "$vif" compression 0
iwpriv "$ifname" compression "$comp" >/dev/null 2>&1
config_get minrate "$vif" minrate
[ -n "$minrate" ] && iwpriv "$ifname" minrate "$minrate"
config_get maxrate "$vif" maxrate
[ -n "$maxrate" ] && iwpriv "$ifname" maxrate "$maxrate"
config_get_bool burst "$vif" bursting
[ -n "$burst" ] && iwpriv "$ifname" burst "$burst"
config_get_bool wmm "$vif" wmm
[ -n "$wmm" ] && iwpriv "$ifname" wmm "$wmm"
config_get_bool xr "$vif" xr
[ -n "$xr" ] && iwpriv "$ifname" xr "$xr"
config_get_bool ar "$vif" ar
[ -n "$ar" ] && iwpriv "$ifname" ar "$ar"
config_get_bool beacon_power "$vif" beacon_power
[ -n "$beacon_power" ] && iwpriv "$ifname" beacon_pwr "$beacon_power"
config_get_bool doth "$vif" doth 0
[ -n "$doth" ] && iwpriv "$ifname" doth "$doth"
config_get_bool probereq "$vif" probereq
[ -n "$probereq" ] && iwpriv "$ifname" probereq "$probereq"
config_get maclist "$vif" maclist
[ -n "$maclist" ] && {
# flush MAC list
iwpriv "$ifname" maccmd 3
for mac in $maclist; do
iwpriv "$ifname" addmac "$mac"
done
}
config_get macpolicy "$vif" macpolicy
case "$macpolicy" in
allow)
iwpriv "$ifname" maccmd 1
;;
deny)
iwpriv "$ifname" maccmd 2
;;
*)
# default deny policy if mac list exists
[ -n "$maclist" ] && iwpriv "$ifname" maccmd 2
;;
esac
ifconfig "$ifname" up
local net_cfg bridge
net_cfg="$(find_net_config "$vif")"
[ -z "$net_cfg" ] || {
bridge="$(bridge_interface "$net_cfg")"
config_set "$vif" bridge "$bridge"
start_net "$ifname" "$net_cfg"
}
config_get ssid "$vif" ssid
[ -n "$ssid" ] && {
iwconfig "$ifname" essid on
iwconfig "$ifname" essid ${ssid:+-- }"$ssid"
}
set_wifi_up "$vif" "$ifname"
# TXPower settings only work if device is up already
# while atheros hardware theoretically is capable of per-vif (even per-packet) txpower
# adjustment it does not work with the current atheros hal/madwifi driver
config_get vif_txpower "$vif" txpower
# use vif_txpower (from wifi-iface) instead of txpower (from wifi-device) if
# the latter doesn't exist
txpower="${txpower:-$vif_txpower}"
[ -z "$txpower" ] || iwconfig "$ifname" txpower "${txpower%%.*}"
case "$mode" in
ap)
config_get_bool isolate "$vif" isolate 0
iwpriv "$ifname" ap_bridge "$((isolate^1))"
if [ -n "$start_hostapd" ] && eval "type hostapd_setup_vif" 2>/dev/null >/dev/null; then
hostapd_setup_vif "$vif" madwifi || {
echo "enable_atheros($device): Failed to set up hostapd for interface $ifname" >&2
# make sure this wifi interface won't accidentally stay open without encryption
ifconfig "$ifname" down
wlanconfig "$ifname" destroy
continue
}
fi
;;
wds|sta)
if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
wpa_supplicant_setup_vif "$vif" wext || {
echo "enable_atheros($device): Failed to set up wpa_supplicant for interface $ifname" >&2
ifconfig "$ifname" down
wlanconfig "$ifname" destroy
continue
}
fi
;;
adhoc)
if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
wpa_supplicant_setup_vif "$vif" madwifi || {
echo "enable_atheros($device): Failed to set up wpa"
ifconfig "$ifname" down
wlanconfig "$ifname" destroy
continue
}
fi
esac
done
}
check_atheros_device() {
[ ${1%[0-9]} = "wifi" ] && config_set "$1" phy "$1"
config_get phy "$1" phy
[ -z "$phy" ] && {
find_atheros_phy "$1" >/dev/null || return 0
config_get phy "$1" phy
}
[ "$phy" = "$dev" ] && found=1
}
detect_atheros() {
devidx=0
config_load wireless
while :; do
config_get type "radio$devidx" type
[ -n "$type" ] || break
devidx=$(($devidx + 1))
done
cd /proc/sys/dev
[ -d ath ] || return
for dev in $(ls -d wifi* 2>&-); do
found=0
config_foreach check_atheros_device wifi-device
[ "$found" -gt 0 ] && continue
devname="$(cat /proc/sys/dev/$dev/dev_name)"
case "$devname" in
"NanoStation Loco2")
EXTRA_DEV="
# Ubiquiti NanoStation Loco2 features
option antenna vertical # (horizontal|vertical)
"
;;
"NanoStation Loco5")
EXTRA_DEV="
# Ubiquiti NanoStation Loco5 features
option antenna auto # (auto|horizontal|vertical)
"
;;
NanoStation*)
EXTRA_DEV="
# Ubiquiti NanoStation features
option antenna auto # (auto|horizontal|vertical|external)
"
;;
esac
cat <<EOF
config wifi-device radio$devidx
option type atheros
option channel auto
option macaddr $(cat /sys/class/net/${dev}/address)
$EXTRA_DEV
# REMOVE THIS LINE TO ENABLE WIFI:
option disabled 1
config wifi-iface
option device radio$devidx
option network lan
option mode ap
option ssid OpenWrt
option encryption none
EOF
devidx=$(($devidx + 1))
done
}

View File

@ -0,0 +1,239 @@
AF 4
AL 8
DZ 12
AS 16
AD 20
AO 24
AI 660
AQ 10
AG 28
AR 32
AM 51
AW 533
AU 36
AT 40
AZ 31
BS 44
BH 48
BD 50
BB 52
BY 112
BE 56
BZ 84
BJ 204
BM 60
BT 64
BO 68
BA 70
BW 72
BV 74
BR 76
IO 86
VG 92
BN 96
BG 100
BF 854
BI 108
KH 116
CM 120
CA 124
CV 132
KY 136
CF 140
TD 148
CL 152
CN 156
CX 162
CC 166
CO 170
KM 174
CD 180
CG 178
CK 184
CR 188
CI 384
CU 192
CY 196
CZ 203
DK 208
DJ 262
DM 212
DO 214
EC 218
EG 818
SV 222
GQ 226
ER 232
EE 233
ET 231
FO 234
FK 238
FJ 242
FI 246
FR 250
GF 254
PF 258
TF 260
GA 266
GM 270
GE 268
DE 276
GH 288
GI 292
GR 300
GL 304
GD 308
GP 312
GU 316
GT 320
GN 324
GW 624
GY 328
HT 332
HM 334
VA 336
HN 340
HK 344
HR 191
HU 348
IS 352
IN 356
ID 360
IR 364
IQ 368
IE 372
IL 376
IT 380
JM 388
JP 392
JO 400
KZ 398
KE 404
KI 296
KP 408
KR 410
KW 414
KG 417
LA 418
LV 428
LB 422
LS 426
LR 430
LY 434
LI 438
LT 440
LU 442
MO 446
MK 807
MG 450
MW 454
MY 458
MV 462
ML 466
MT 470
MH 584
MQ 474
MR 478
MU 480
YT 175
MX 484
FM 583
MD 498
MC 492
MN 496
MS 500
MA 504
MZ 508
MM 104
NA 516
NR 520
NP 524
AN 530
NL 528
NC 540
NZ 554
NI 558
NE 562
NG 566
NU 570
NF 574
MP 580
NO 578
OM 512
PK 586
PW 585
PS 275
PA 591
PG 598
PY 600
PE 604
PH 608
PN 612
PL 616
PT 620
PR 630
QA 634
RE 638
RO 642
RU 643
RW 646
SH 654
KN 659
LC 662
PM 666
VC 670
WS 882
SM 674
ST 678
SA 682
SN 686
CS 891
SC 690
SL 694
SG 702
SK 703
SI 705
SB 90
SO 706
ZA 710
GS 239
ES 724
LK 144
SD 736
SR 740
SJ 744
SZ 748
SE 752
CH 756
SY 760
TW 158
TJ 762
TZ 834
TH 764
TL 626
TG 768
TK 772
TO 776
TT 780
TN 788
TR 792
TM 795
TC 796
TV 798
VI 850
UG 800
UA 804
AE 784
GB 826
UM 581
US 840
UY 858
UZ 860
VU 548
VE 862
VN 704
WF 876
EH 732
YE 887
ZM 894
ZW 716

View File

@ -0,0 +1,315 @@
--- a/tools/80211debug.c
+++ b/tools/80211debug.c
@@ -48,6 +48,7 @@
#include <ctype.h>
#include <getopt.h>
#include <err.h>
+#include "do_multi.h"
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -185,7 +186,7 @@ sysctlbyname(const char *oid0, void *old
#endif /* __linux__ */
int
-main(int argc, char *argv[])
+CMD(a80211debug)(int argc, char *argv[])
{
const char *ifname = "ath0";
const char *cp, *tp;
--- a/tools/80211stats.c
+++ b/tools/80211stats.c
@@ -59,6 +59,7 @@
#include "net80211/ieee80211.h"
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
+#include "do_multi.h"
#ifndef SIOCG80211STATS
#define SIOCG80211STATS (SIOCDEVPRIVATE + 2)
@@ -240,7 +241,7 @@ print_sta_stats(FILE *fd, const u_int8_t
}
int
-main(int argc, char *argv[])
+CMD(a80211stats)(int argc, char *argv[])
{
int c, len;
struct ieee80211req_sta_info *si;
--- a/tools/athchans.c
+++ b/tools/athchans.c
@@ -58,6 +58,7 @@
#include "net80211/ieee80211.h"
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
+#include "do_multi.h"
static int s = -1;
static const char *progname;
@@ -140,8 +141,9 @@ usage(void)
}
#define MAXCHAN ((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
+
int
-main(int argc, char *argv[])
+CMD(athchans)(int argc, char *argv[])
{
const char *ifname = "wifi0";
struct ieee80211req_chanlist chanlist;
--- a/tools/athctrl.c
+++ b/tools/athctrl.c
@@ -52,6 +52,7 @@
#include <err.h>
#include <net/if.h>
+#include "do_multi.h"
static int
setsysctrl(const char *dev, const char *control , u_long value)
@@ -88,7 +89,7 @@ static void usage(void)
}
int
-main(int argc, char *argv[])
+CMD(athctrl)(int argc, char *argv[])
{
char device[IFNAMSIZ + 1];
int distance = -1;
--- a/tools/athdebug.c
+++ b/tools/athdebug.c
@@ -51,6 +51,7 @@
#include <ctype.h>
#include <getopt.h>
#include <err.h>
+#include "do_multi.h"
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -194,7 +195,7 @@ sysctlbyname(const char *oid0, void *old
#endif /* __linux__ */
int
-main(int argc, char *argv[])
+CMD(athdebug)(int argc, char *argv[])
{
#ifdef __linux__
const char *ifname = "wifi0";
--- a/tools/athkey.c
+++ b/tools/athkey.c
@@ -58,6 +58,7 @@
#include "net80211/ieee80211.h"
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
+#include "do_multi.h"
static int s = -1;
static const char *progname;
@@ -213,8 +214,7 @@ usage(void)
exit(-1);
}
-int
-main(int argc, char *argv[])
+int CMD(athkey)(int argc, char *argv[])
{
const char *ifname = "wifi0";
struct ieee80211req_key setkey;
--- a/tools/athstats.c
+++ b/tools/athstats.c
@@ -65,6 +65,7 @@
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#include "do_multi.h"
static const struct {
u_int phyerr;
@@ -228,7 +229,7 @@ catchalarm(int signo)
}
int
-main(int argc, char *argv[])
+CMD(athstats)(int argc, char *argv[])
{
#ifdef __linux__
const char *ifname = "wifi0";
--- /dev/null
+++ b/tools/do_multi.c
@@ -0,0 +1,33 @@
+#include <string.h>
+#include <libgen.h>
+#include "do_multi.h"
+
+int
+main(int argc, char *argv[])
+{
+ char *progname;
+ int ret = 0;
+
+ progname = basename(argv[0]);
+
+ if(strcmp(progname, "80211debug") == 0)
+ ret = a80211debug_init(argc, argv);
+ if(strcmp(progname, "80211stats") == 0)
+ ret = a80211stats_init(argc, argv);
+ if(strcmp(progname, "athchans") == 0)
+ ret = athchans_init(argc, argv);
+ if(strcmp(progname, "athctrl") == 0)
+ ret = athctrl_init(argc, argv);
+ if(strcmp(progname, "athdebug") == 0)
+ ret = athdebug_init(argc, argv);
+ if(strcmp(progname, "athkey") == 0)
+ ret = athkey_init(argc, argv);
+ if(strcmp(progname, "athstats") == 0)
+ ret = athstats_init(argc, argv);
+ if(strcmp(progname, "wlanconfig") == 0)
+ ret = wlanconfig_init(argc, argv);
+ if(strcmp(progname, "ath_info") == 0)
+ ret = athinfo_init(argc, argv);
+
+ return ret;
+}
--- /dev/null
+++ b/tools/do_multi.h
@@ -0,0 +1,15 @@
+#ifdef DO_MULTI
+int a80211debug_init(int argc, char *argv[]);
+int a80211stats_init(int argc, char *argv[]);
+int athchans_init(int argc, char *argv[]);
+int athctrl_init(int argc, char *argv[]);
+int athdebug_init(int argc, char *argv[]);
+int athkey_init(int argc, char *argv[]);
+int athstats_init(int argc, char *argv[]);
+int wlanconfig_init(int argc, char *argv[]);
+int athinfo_init(int argc, char *argv[]);
+
+#define CMD(name) name##_init
+#else
+#define CMD(name) main
+#endif
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -46,56 +46,55 @@ ifeq ($(HAL),)
HAL= $(TOP)/hal
endif
+all: compile
-ALL= athstats 80211stats athkey athchans athctrl \
+ALLPROGS= athstats 80211stats athkey athchans athctrl \
athdebug 80211debug wlanconfig ath_info
-all: $(ALL)
+OBJS= $(patsubst %,%.o,$(ALLPROGS))
-INCS= -I. -I$(HAL) -I$(TOP) -I$(ATH_HAL)
+INCS= -I. -I../ath -I$(HAL) -I$(TOP) -I$(ATH_HAL)
CFLAGS= -g -O2 -Wall
ALL_CFLAGS= $(CFLAGS) $(INCS)
LDFLAGS=
-all: $(ALL)
-athstats: athstats.c
- $(CC) -o athstats $(ALL_CFLAGS) -I$(TOP)/ath $(LDFLAGS) athstats.c
-80211stats: 80211stats.c
- $(CC) -o 80211stats $(ALL_CFLAGS) $(LDFLAGS) 80211stats.c
-athkey: athkey.c
- $(CC) -o athkey $(ALL_CFLAGS) $(LDFLAGS) athkey.c
-athchans: athchans.c
- $(CC) -o athchans $(ALL_CFLAGS) $(LDFLAGS) athchans.c
-athctrl: athctrl.c
- $(CC) -o athctrl $(ALL_CFLAGS) $(LDFLAGS) athctrl.c
-athdebug: athdebug.c
- $(CC) -o athdebug $(ALL_CFLAGS) $(LDFLAGS) athdebug.c
-wlanconfig: wlanconfig.c
- $(CC) -o wlanconfig $(ALL_CFLAGS) $(LDFLAGS) wlanconfig.c
-80211debug: 80211debug.c
- $(CC) -o 80211debug $(ALL_CFLAGS) $(LDFLAGS) 80211debug.c
-ath_info: ath_info.c
- $(CC) -o ath_info $(CFLAGS) ath_info.c
+ifneq ($(DO_MULTI),)
+ALL_CFLAGS += -DDO_MULTI=1
+%.o: %.c
+ ${CC} $(ALL_CFLAGS) -c -o $@ $<
+
+madwifi_multi: $(OBJS) do_multi.o
+ $(CC) -o $@ $^
+
+compile: madwifi_multi
+ for i in $(ALLPROGS); do \
+ ln -s -f madwifi_multi $$i; \
+ done
+else
+$(ALLPROGS):
+ $(CC) $(ALL_CFLAGS) -o $@ $@.c
+
+compile: $(ALLPROGS)
+endif
install: $(ALL)
install -d $(DESTDIR)$(BINDIR)
- for i in $(ALL); do \
+ for i in $(ALLPROGS) $(if $(DO_MULTI),madwifi_multi); do \
install $$i $(DESTDIR)$(BINDIR)/$$i; \
- $(STRIP) $(DESTDIR)$(BINDIR)/$$i; \
done
install -d $(DESTDIR)$(MANDIR)/man8
install -m 0644 man/*.8 $(DESTDIR)$(MANDIR)/man8
install $(TOP)/scripts/madwifi-unload $(DESTDIR)$(BINDIR)/madwifi-unload
uninstall:
- for i in $(ALL); do \
+ for i in $(ALLPROGS) $(if $(DO_MULTI),madwifi_multi); do \
rm -f $(DESTDIR)$(BINDIR)/$$i; \
done
- for i in $(ALL:=.8); do \
- rm -f $(DESTDIR)$(MANDIR)/man8/$$i; \
+ for i in $(ALLPROGS); do \
+ rm -f $(DESTDIR)$(MANDIR)/man8/$$i.8; \
done
clean:
- rm -f $(ALL) core a.out
+ rm -f $(ALLPROGS) madwifi_multi *.o core a.out
--- a/tools/wlanconfig.c
+++ b/tools/wlanconfig.c
@@ -61,6 +61,7 @@
#include "net80211/ieee80211.h"
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
+#include "do_multi.h"
/*
* These are taken from ieee80211_node.h
@@ -100,7 +101,7 @@ size_t strlcat(char *, const char *, siz
static int verbose = 0;
int
-main(int argc, char *argv[])
+CMD(wlanconfig)(int argc, char *argv[])
{
const char *ifname, *cmd;
unsigned char bnounit = 0;
--- a/tools/ath_info.c
+++ b/tools/ath_info.c
@@ -98,6 +98,7 @@
#include <sys/mman.h>
#include <endian.h>
#include <byteswap.h>
+#include "do_multi.h"
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -738,7 +739,8 @@ static void usage(const char *n)
"unlawful radio transmissions!\n\n");
}
-int main(int argc, char *argv[])
+int
+CMD(athinfo)(int argc, char *argv[])
{
u_int32_t dev_addr;
u_int16_t eeprom_header, srev, phy_rev_5ghz, phy_rev_2ghz;

View File

@ -0,0 +1,11 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -516,7 +516,7 @@ ath_attach(u_int16_t devid, struct net_d
HAL_STATUS status;
int error = 0;
unsigned int i;
- int autocreatemode = IEEE80211_M_STA;
+ int autocreatemode = -1;
u_int8_t csz;
sc->devid = devid;

View File

@ -0,0 +1,23 @@
--- a/net80211/ieee80211_rate.c
+++ b/net80211/ieee80211_rate.c
@@ -100,8 +100,18 @@ struct ath_ratectrl *ieee80211_rate_atta
ieee80211_load_module(buf);
if (!ratectls[id].attach) {
- printk(KERN_ERR "Error loading module \"%s\"\n", buf);
- return NULL;
+ /* pick the first available rate control module */
+ printk(KERN_INFO "Rate control module \"%s\" not available\n", buf);
+ for (id = 0; id < IEEE80211_RATE_MAX - 1; id++) {
+ if (ratectls[id].attach)
+ break;
+ }
+ if (!ratectls[id].attach) {
+ printk(KERN_ERR "No rate control module available");
+ return NULL;
+ } else {
+ printk(KERN_INFO "Using \"%s\" instead.\n", module_names[id]);
+ }
}
ctl = ratectls[id].attach(sc);

View File

@ -0,0 +1,21 @@
--- a/scripts/get_arch.mk
+++ b/scripts/get_arch.mk
@@ -36,11 +36,14 @@ ifeq (,$(ARCH-y))
$(Cannot determine ARCH)
endif
+# Allow ARCH to be x86
+ifneq (,$(CONFIG_X86))
+ifeq (x86,$(ARCH))
+ARCH-y = $(ARCH)
+endif
+endif
+
# Don't allow ARCH to be overridden by a different value.
ifeq (,$(ARCH))
ARCH = $(ARCH-y)
-else
-ifneq ($(ARCH),$(ARCH-y))
-$(error ARCH mismatch: supplied "$(ARCH)", determined "$(ARCH-y)")
-endif
endif

View File

@ -0,0 +1,12 @@
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -393,6 +393,9 @@ ath_rate_get_mrr(struct ath_softc *sc, s
struct minstrel_node *sn = ATH_NODE_MINSTREL(an);
int rc1, rc2, rc3; /* Index into the rate table, so for example, it is 0..11 */
+ if (sn->num_rates <= 0)
+ return;
+
if (sn->is_sampling) {
sn->is_sampling = 0;
if (sn->rs_sample_rate_slower)

View File

@ -0,0 +1,12 @@
--- a/net80211/ieee80211_scan.c
+++ b/net80211/ieee80211_scan.c
@@ -291,7 +291,8 @@ scan_restart_pwrsav(unsigned long arg)
struct ieee80211com *ic = vap->iv_ic;
int delay;
- ieee80211_sta_pwrsave(vap, 1);
+ if (vap->iv_opmode != IEEE80211_M_IBSS)
+ ieee80211_sta_pwrsave(vap, 1);
/*
* Use an initial 1ms delay to ensure the null
* data frame has a chance to go out.

View File

@ -0,0 +1,12 @@
--- a/net80211/ieee80211_linux.c
+++ b/net80211/ieee80211_linux.c
@@ -331,6 +331,9 @@ ieee80211_notify_replay_failure(struct i
k->wk_cipher->ic_name, k->wk_keyix,
(unsigned long long)rsc);
+ /* disabled for now due to bogus events for unknown reasons */
+ return;
+
/* TODO: needed parameters: count, keyid, key type, src address, TSC */
snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,
k->wk_keyix,

View File

@ -0,0 +1,95 @@
--- a/net80211/ieee80211_crypto_ccmp.c
+++ b/net80211/ieee80211_crypto_ccmp.c
@@ -115,6 +115,7 @@ ccmp_attach(struct ieee80211vap *vap, st
/* This function (crypto_alloc_foo might sleep. Therefore:
* Context: process
*/
+#ifdef CONFIG_CRYPTO
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
ctx->cc_tfm = crypto_alloc_tfm("aes", 0);
#else
@@ -123,7 +124,8 @@ ccmp_attach(struct ieee80211vap *vap, st
if (IS_ERR(ctx->cc_tfm))
ctx->cc_tfm = NULL;
#endif
-
+#endif
+
if (ctx->cc_tfm == NULL) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
"%s: unable to load kernel AES crypto support\n",
@@ -138,12 +140,14 @@ ccmp_detach(struct ieee80211_key *k)
{
struct ccmp_ctx *ctx = k->wk_private;
+#ifdef CONFIG_CRYPTO
if (ctx->cc_tfm != NULL)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
crypto_free_tfm(ctx->cc_tfm);
#else
crypto_free_cipher(ctx->cc_tfm);
#endif
+#endif
FREE(ctx, M_DEVBUF);
_MOD_DEC_USE(THIS_MODULE);
@@ -169,7 +173,9 @@ ccmp_setkey(struct ieee80211_key *k)
return 0;
}
+#ifdef CONFIG_CRYPTO
crypto_cipher_setkey(ctx->cc_tfm, k->wk_key, k->wk_keylen);
+#endif
}
return 1;
@@ -324,6 +330,7 @@ xor_block(u8 *b, const u8 *a, size_t len
static void
rijndael_encrypt(struct crypto_cipher *tfm, const void *src, void *dst)
{
+#ifdef CONFIG_CRYPTO
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
crypto_cipher_encrypt_one(tfm, dst, src);
#else
@@ -339,6 +346,7 @@ rijndael_encrypt(struct crypto_cipher *t
sg_dst.length = AES_BLOCK_LEN;
crypto_cipher_encrypt(tfm, &sg_dst, &sg_src, AES_BLOCK_LEN);
#endif
+#endif
}
/*
@@ -475,6 +483,9 @@ ccmp_encrypt(struct ieee80211_key *key,
uint8_t *mic, *pos;
u_int space;
+ if (ctx->cc_tfm == NULL)
+ return 0;
+
ctx->cc_vap->iv_stats.is_crypto_ccmp++;
skb = skb0;
@@ -589,6 +600,9 @@ ccmp_decrypt(struct ieee80211_key *key,
uint8_t *pos, *mic;
u_int space;
+ if (ctx->cc_tfm == NULL)
+ return 0;
+
ctx->cc_vap->iv_stats.is_crypto_ccmp++;
skb = skb0;
--- a/Makefile
+++ b/Makefile
@@ -192,11 +192,4 @@ endif
exit 1; \
fi
- @# check crypto support is enabled
- @if [ -z "$(CONFIG_CRYPTO)" ]; then \
- echo "FAILED"; \
- echo "Please enable crypto API."; \
- exit 1; \
- fi
-
@echo "ok."

View File

@ -0,0 +1,202 @@
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -126,6 +126,11 @@ typedef void irqreturn_t;
#define ATH_GET_NETDEV_DEV(ndev) ((ndev)->class_dev.dev)
#endif
+#ifndef NETDEV_TX_OK
+#define NETDEV_TX_OK 0
+#define NETDEV_TX_BUSY 1
+#endif
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
static inline struct net_device *_alloc_netdev(int sizeof_priv, const char *mask,
void (*setup)(struct net_device *))
--- a/ath/if_ath_radar.c
+++ b/ath/if_ath_radar.c
@@ -92,6 +92,13 @@
#define nofloat_pct(_value, _pct) \
( (_value * (1000 + _pct)) / 1000 )
+#ifndef list_for_each_entry_reverse
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+#endif
+
struct radar_pattern_specification {
/* The name of the rule/specification (i.e. what did we detect) */
const char *name;
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -4705,6 +4705,46 @@ ath_beacon_setup(struct ath_softc *sc, s
#undef USE_SHPREAMBLE
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+ int ret;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ret = v->counter;
+ if (likely(ret == old))
+ v->counter = new;
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int c, old;
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c == (u)))
+ break;
+ old = atomic_cmpxchg((v), c, c + (a));
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return c != (u);
+}
+#endif
+
/*
* Generate beacon frame and queue cab data for a VAP.
*/
--- /dev/null
+++ b/net80211/sort.c
@@ -0,0 +1,120 @@
+/*
+ * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
+ *
+ * Jan 23 2005 Matt Mackall <mpm@selenic.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+static void u32_swap(void *a, void *b, int size)
+{
+ u32 t = *(u32 *)a;
+ *(u32 *)a = *(u32 *)b;
+ *(u32 *)b = t;
+}
+
+static void generic_swap(void *a, void *b, int size)
+{
+ char t;
+
+ do {
+ t = *(char *)a;
+ *(char *)a++ = *(char *)b;
+ *(char *)b++ = t;
+ } while (--size > 0);
+}
+
+/**
+ * sort - sort an array of elements
+ * @base: pointer to data to sort
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ * @swap: pointer to swap function or NULL
+ *
+ * This function does a heapsort on the given array. You may provide a
+ * swap function optimized to your element type.
+ *
+ * Sorting time is O(n log n) both on average and worst-case. While
+ * qsort is about 20% faster on average, it suffers from exploitable
+ * O(n*n) worst-case behavior and extra memory requirements that make
+ * it less suitable for kernel use.
+ */
+
+static void sort(void *base, size_t num, size_t size,
+ int (*cmp)(const void *, const void *),
+ void (*swap)(void *, void *, int size))
+{
+ /* pre-scale counters for performance */
+ int i = (num/2 - 1) * size, n = num * size, c, r;
+
+ if (!swap)
+ swap = (size == 4 ? u32_swap : generic_swap);
+
+ /* heapify */
+ for ( ; i >= 0; i -= size) {
+ for (r = i; r * 2 + size < n; r = c) {
+ c = r * 2 + size;
+ if (c < n - size && cmp(base + c, base + c + size) < 0)
+ c += size;
+ if (cmp(base + r, base + c) >= 0)
+ break;
+ swap(base + r, base + c, size);
+ }
+ }
+
+ /* sort */
+ for (i = n - size; i >= 0; i -= size) {
+ swap(base, base + i, size);
+ for (r = 0; r * 2 + size < i; r = c) {
+ c = r * 2 + size;
+ if (c < i - size && cmp(base + c, base + c + size) < 0)
+ c += size;
+ if (cmp(base + r, base + c) >= 0)
+ break;
+ swap(base + r, base + c, size);
+ }
+ }
+}
+
+EXPORT_SYMBOL(sort);
+
+#if 0
+/* a simple boot-time regression test */
+
+int cmpint(const void *a, const void *b)
+{
+ return *(int *)a - *(int *)b;
+}
+
+static int sort_test(void)
+{
+ int *a, i, r = 1;
+
+ a = kmalloc(1000 * sizeof(int), GFP_KERNEL);
+ BUG_ON(!a);
+
+ printk("testing sort()\n");
+
+ for (i = 0; i < 1000; i++) {
+ r = (r * 725861) % 6599;
+ a[i] = r;
+ }
+
+ sort(a, 1000, sizeof(int), cmpint, NULL);
+
+ for (i = 0; i < 999; i++)
+ if (a[i] > a[i+1]) {
+ printk("sort() failed!\n");
+ break;
+ }
+
+ kfree(a);
+
+ return 0;
+}
+
+module_init(sort_test);
+#endif

View File

@ -0,0 +1,13 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6474,8 +6474,9 @@ ath_rx_tasklet(TQUEUE_ARG data)
/*
* Reject error frames if we have no vaps that
* are operating in monitor mode.
+ * Reject empty frames as well
*/
- if (sc->sc_nmonvaps == 0)
+ if ((sc->sc_nmonvaps == 0) || (rs->rs_datalen == 0))
goto rx_next;
}
rx_accept:

View File

@ -0,0 +1,408 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -42,7 +42,6 @@
* This software is derived from work of Atsushi Onoe; his contribution
* is greatly appreciated.
*/
-#define AR_DEBUG
#include "if_ath_debug.h"
#include "opt_ah.h"
@@ -368,8 +367,10 @@ static unsigned int ath_get_dfs_cac_time
static void ath_set_dfs_cac_time(struct ieee80211com *, unsigned int seconds);
static unsigned int ath_test_radar(struct ieee80211com *);
-static unsigned int ath_dump_hal_map(struct ieee80211com *ic);
+#ifdef AR_DEBUG
+static unsigned int ath_dump_hal_map(struct ieee80211com *ic);
+#endif
static u_int32_t ath_get_clamped_maxtxpower(struct ath_softc *sc);
static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc,
u_int32_t new_clamped_maxtxpower);
@@ -520,9 +521,11 @@ ath_attach(u_int16_t devid, struct net_d
u_int8_t csz;
sc->devid = devid;
+#ifdef AR_DEBUG
ath_debug_global = (ath_debug & ATH_DEBUG_GLOBAL);
sc->sc_debug = (ath_debug & ~ATH_DEBUG_GLOBAL);
DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
+#endif
/* Allocate space for dynamically determined maximum VAP count */
sc->sc_bslot =
@@ -1038,8 +1041,9 @@ ath_attach(u_int16_t devid, struct net_d
ic->ic_vap_delete = ath_vap_delete;
ic->ic_test_radar = ath_test_radar;
+#ifdef AR_DEBUG
ic->ic_dump_hal_map = ath_dump_hal_map;
-
+#endif
ic->ic_set_dfs_testmode = ath_set_dfs_testmode;
ic->ic_get_dfs_testmode = ath_get_dfs_testmode;
@@ -1297,12 +1301,14 @@ ath_vap_create(struct ieee80211com *ic,
/* If no default VAP debug flags are passed, allow a few to
* transfer down from the driver to new VAPs so we can have load
* time debugging for VAPs too. */
+#ifdef AR_DEBUG
vap->iv_debug = 0 |
((sc->sc_debug & ATH_DEBUG_RATE) ? IEEE80211_MSG_XRATE : 0) |
((sc->sc_debug & ATH_DEBUG_XMIT) ? IEEE80211_MSG_OUTPUT : 0) |
((sc->sc_debug & ATH_DEBUG_RECV) ? IEEE80211_MSG_INPUT : 0) |
0
;
+#endif
}
ic->ic_debug = (sc->sc_default_ieee80211_debug & IEEE80211_MSG_IC);
@@ -10496,9 +10502,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
/* XXX validate? */
sc->sc_ledpin = val;
break;
+#ifdef AR_DEBUG
case ATH_DEBUG:
sc->sc_debug = (val & ~ATH_DEBUG_GLOBAL);
ath_debug_global = (val & ATH_DEBUG_GLOBAL);
+#endif
break;
case ATH_TXANTENNA:
/*
@@ -10918,9 +10926,11 @@ ath_dynamic_sysctl_register(struct ath_s
}
/* initialize values */
+#ifdef AR_DEBUG
ath_debug_global = (ath_debug & ATH_DEBUG_GLOBAL);
sc->sc_debug = (ath_debug & ~ATH_DEBUG_GLOBAL);
sc->sc_default_ieee80211_debug = ieee80211_debug;
+#endif
sc->sc_txantenna = 0; /* default to auto-selection */
sc->sc_txintrperiod = ATH_TXQ_INTR_PERIOD;
}
@@ -11762,6 +11772,7 @@ ath_test_radar(struct ieee80211com *ic)
}
/* This is called by a private ioctl (iwpriv) to dump the HAL obfuscation table */
+#ifdef AR_DEBUG
static unsigned int
ath_dump_hal_map(struct ieee80211com *ic)
{
@@ -11770,7 +11781,7 @@ ath_dump_hal_map(struct ieee80211com *ic
ath_hal_dump_map(sc->sc_ah);
return 0;
}
-
+#endif
/* If we are shutting down or blowing off the DFS channel availability check
* then we call this to stop the behavior before we take the rest of the
* necessary actions (such as a DFS reaction to radar). */
--- a/ath_rate/amrr/amrr.c
+++ b/ath_rate/amrr/amrr.c
@@ -70,7 +70,9 @@
#include "amrr.h"
+#ifdef AR_DEBUG
#define AMRR_DEBUG
+#endif
#ifdef AMRR_DEBUG
#define DPRINTF(sc, _fmt, ...) do { \
if (sc->sc_debug & 0x10) \
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -117,7 +117,9 @@
#include "minstrel.h"
+#ifdef AR_DEBUG
#define MINSTREL_DEBUG
+#endif
#ifdef MINSTREL_DEBUG
enum {
ATH_DEBUG_RATE = 0x00000010 /* rate control */
--- a/ath_rate/onoe/onoe.c
+++ b/ath_rate/onoe/onoe.c
@@ -66,7 +66,9 @@
#include "onoe.h"
+#ifdef AR_DEBUG
#define ONOE_DEBUG
+#endif
#ifdef ONOE_DEBUG
enum {
ATH_DEBUG_RATE = 0x00000010, /* rate control */
--- a/ath_rate/sample/sample.c
+++ b/ath_rate/sample/sample.c
@@ -68,7 +68,9 @@
#include "sample.h"
-#define SAMPLE_DEBUG
+#ifdef AR_DEBUG
+#define SAMPLE_DEBUG
+#endif
#ifdef SAMPLE_DEBUG
enum {
ATH_DEBUG_RATE = 0x00000010, /* rate control */
--- a/tools/do_multi.c
+++ b/tools/do_multi.c
@@ -10,16 +10,20 @@ main(int argc, char *argv[])
progname = basename(argv[0]);
+#ifdef AR_DEBUG
if(strcmp(progname, "80211debug") == 0)
ret = a80211debug_init(argc, argv);
+#endif
if(strcmp(progname, "80211stats") == 0)
ret = a80211stats_init(argc, argv);
if(strcmp(progname, "athchans") == 0)
ret = athchans_init(argc, argv);
if(strcmp(progname, "athctrl") == 0)
ret = athctrl_init(argc, argv);
+#ifdef AR_DEBUG
if(strcmp(progname, "athdebug") == 0)
ret = athdebug_init(argc, argv);
+#endif
if(strcmp(progname, "athkey") == 0)
ret = athkey_init(argc, argv);
if(strcmp(progname, "athstats") == 0)
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -48,14 +48,16 @@ endif
all: compile
+DEBUG = -DAR_DEBUG
+
ALLPROGS= athstats 80211stats athkey athchans athctrl \
- athdebug 80211debug wlanconfig ath_info
+ $(if $(DEBUG),athdebug 80211debug) wlanconfig ath_info
OBJS= $(patsubst %,%.o,$(ALLPROGS))
INCS= -I. -I../ath -I$(HAL) -I$(TOP) -I$(ATH_HAL)
CFLAGS= -g -O2 -Wall
-ALL_CFLAGS= $(CFLAGS) $(INCS)
+ALL_CFLAGS= $(CFLAGS) $(INCS) $(DEBUG)
LDFLAGS=
--- a/net80211/ieee80211_linux.h
+++ b/net80211/ieee80211_linux.h
@@ -29,8 +29,6 @@
#ifndef _NET80211_IEEE80211_LINUX_H_
#define _NET80211_IEEE80211_LINUX_H_
-#define IEEE80211_DEBUG
-#define IEEE80211_DEBUG_REFCNT /* Node reference count debugging */
/* #define ATH_DEBUG_SPINLOCKS */ /* announce before spinlocking */
#include <linux/wireless.h>
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -147,8 +147,9 @@ ATH_RATE= $(TOP)/ath_rate
#
TOOLS= $(TOP)/tools
-WARNINGS = -Werror
-COPTS+= $(WARNINGS)
+WARNINGS = -Wno-unused
+# DEBUG = -DAR_DEBUG -DIEEE80211_DEBUG
+COPTS+= $(WARNINGS) $(DEBUG)
INCS= -include $(TOP)/include/compat.h -I$(TOP)/include
# TARGET defines the target platform architecture. It must match one of
--- a/ath/if_ath_radar.c
+++ b/ath/if_ath_radar.c
@@ -19,8 +19,6 @@
* $Id: if_ath_radar.c 2464 2007-06-15 22:51:56Z mtaylor $
*/
#include "opt_ah.h"
-
-#define AR_DEBUG
#include "if_ath_debug.h"
#ifndef AUTOCONF_INCLUDED
@@ -56,8 +54,6 @@
#include <net80211/if_llc.h>
#endif
-#define AR_DEBUG
-
#include "net80211/if_athproto.h"
#include "if_athvar.h"
--- a/ath/if_ath_hal.h
+++ b/ath/if_ath_hal.h
@@ -1081,6 +1081,7 @@ static inline HAL_BOOL ath_hal_disable(s
tail -f /var/log/messages | sed -f hal_unmangle.sed
*/
+#ifdef AR_DEBUG
static inline void ath_hal_dump_map(struct ath_hal *ah)
{
#ifdef CONFIG_KALLSYMS
@@ -1345,7 +1346,7 @@ static inline void ath_hal_dump_map(stru
#endif /* #ifndef CONFIG_KALLSYMS */
}
-
+#endif
#include "if_ath_hal_wrappers.h"
#endif /* #ifndef _IF_ATH_HAL_H_ */
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -492,9 +492,10 @@ struct ieee80211com {
/* inject a fake radar signal -- used while on a 802.11h DFS channels */
unsigned int (*ic_test_radar)(struct ieee80211com *);
+#ifdef AR_DEBUG
/* dump HAL */
unsigned int (*ic_dump_hal_map)(struct ieee80211com *);
-
+#endif
/* DFS channel availability check time (in seconds) */
void (*ic_set_dfs_cac_time)(struct ieee80211com *, unsigned int);
unsigned int (*ic_get_dfs_cac_time)(struct ieee80211com *);
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -1548,6 +1548,7 @@ ieee80211_get_txcont_power(struct net_de
return 0;
}
+#ifdef AR_DEBUG
static int
ieee80211_ioctl_hal_map(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
@@ -1558,7 +1559,7 @@ ieee80211_ioctl_hal_map(struct net_devic
params[0] = ic->ic_dump_hal_map(ic);
return 0;
}
-
+#endif
static int
ieee80211_ioctl_radar(struct net_device *dev, struct iw_request_info *info,
@@ -5258,8 +5259,10 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwmmparams" },
{ IEEE80211_IOCTL_RADAR,
0, 0, "doth_radar" },
+#ifdef AR_DEBUG
{ IEEE80211_IOCTL_HALMAP,
0, 0, "dump_hal_map" },
+#endif
/*
* These depends on sub-ioctl support which added in version 12.
*/
@@ -5695,7 +5698,9 @@ static const iw_handler ieee80211_priv_h
set_priv(IEEE80211_IOCTL_SETMLME, ieee80211_ioctl_setmlme),
set_priv(IEEE80211_IOCTL_SETKEY, ieee80211_ioctl_setkey),
set_priv(IEEE80211_IOCTL_DELKEY, ieee80211_ioctl_delkey),
+#ifdef AR_DEBUG
set_priv(IEEE80211_IOCTL_HALMAP, ieee80211_ioctl_hal_map),
+#endif
set_priv(IEEE80211_IOCTL_ADDMAC, ieee80211_ioctl_addmac),
set_priv(IEEE80211_IOCTL_DELMAC, ieee80211_ioctl_delmac),
set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
--- a/ath/if_ath_debug.h
+++ b/ath/if_ath_debug.h
@@ -54,6 +54,10 @@ enum {
ATH_DEBUG_GLOBAL = (ATH_DEBUG_SKB|ATH_DEBUG_SKB_REF)
};
+#define EPRINTF(_sc, _fmt, ...) \
+ printk(KERN_ERR "%s: %s: " _fmt, \
+ SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
+
#ifdef AR_DEBUG
/* DEBUG-ONLY DEFINITIONS */
@@ -68,20 +72,9 @@ enum {
ath_keyprint((_sc), __func__, _ix, _hk, _mac); \
} while (0)
-#else /* #ifdef AR_DEBUG */
-
-#define DFLAG_ISSET(sc, _m) 0
-#define DPRINTF(sc, _m, _fmt, ...)
-#define KEYPRINTF(sc, k, ix, mac)
-
-#endif /* #ifdef AR_DEBUG */
#define IFF_DUMPPKTS(_sc, _m) DFLAG_ISSET((_sc), (_m))
-#define EPRINTF(_sc, _fmt, ...) \
- printk(KERN_ERR "%s: %s: " _fmt, \
- SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
-
#define WPRINTF(_sc, _fmt, ...) \
printk(KERN_WARNING "%s: %s: " _fmt, \
SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
@@ -89,5 +82,14 @@ enum {
#define IPRINTF(_sc, _fmt, ...) \
printk(KERN_INFO "%s: %s: " _fmt, \
SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
+#else
+#define DFLAG_ISSET(sc, _m) 0
+#define DPRINTF(sc, _m, _fmt, ...)
+#define KEYPRINTF(sc, k, ix, mac)
+#define WPRINTF(...)
+#define IPRINTF(...)
+#define IFF_DUMPPKTS(...) 0
+
+#endif
#endif /* #ifndef _IF_ATH_DEBUG_H_ */
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -920,6 +920,9 @@ node_cleanup(struct ieee80211_node *ni)
ni->ni_rxkeyoff = 0;
}
+#ifndef IEEE80211_DEBUG
+#define node_print_message(...) do {} while(0)
+#else
static void node_print_message(
u_int32_t flags,
int show_counter,
@@ -972,7 +975,7 @@ static void node_print_message(
adjusted_refcount);
va_end(args);
}
-EXPORT_SYMBOL(node_print_message);
+#endif
static void
#ifdef IEEE80211_DEBUG_REFCNT
--- a/ath/if_ath_pci.c
+++ b/ath/if_ath_pci.c
@@ -134,8 +134,10 @@ ath_pci_probe(struct pci_dev *pdev, cons
u16 vdevice;
int i;
- if (pci_enable_device(pdev))
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "%s: failed to enable PCI device\n", dev_info);
return -EIO;
+ }
/* XXX 32-bit addressing only */
if (pci_set_dma_mask(pdev, 0xffffffff)) {
@@ -244,8 +246,10 @@ ath_pci_probe(struct pci_dev *pdev, cons
sc->aps_sc.sc_ledpin = 1;
}
- if (ath_attach(vdevice, dev, NULL) != 0)
+ if ((i = ath_attach(vdevice, dev, NULL)) != 0) {
+ printk(KERN_ERR "%s: ath_attach failed: %d\n", dev_info, i);
goto bad4;
+ }
athname = ath_hal_probe(id->vendor, vdevice);
printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",

View File

@ -0,0 +1,20 @@
--- a/ath_hal/ah_os.c
+++ b/ath_hal/ah_os.c
@@ -65,7 +65,7 @@
#include <ah_os.h>
#ifdef AH_DEBUG
-static int ath_hal_debug = 0;
+static int ath_hal_debug = 99;
#endif
int ath_hal_dma_beacon_response_time = 2; /* in TUs */
@@ -327,6 +327,8 @@ EXPORT_SYMBOL(OS_MARK);
* useful for debugging and figuring out, which hal function sets which
* registers */
char *ath_hal_func = NULL;
+EXPORT_SYMBOL(ath_hal_func);
+
#endif
/*

View File

@ -0,0 +1,204 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -453,8 +453,8 @@ MODULE_PARM_DESC(autocreate, "Create ath
MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], "
"defaults to '" DEF_RATE_CTL "'");
-static int ath_debug = 0;
#ifdef AR_DEBUG
+static int ath_debug = 0;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
MODULE_PARM(ath_debug, "i");
#else
@@ -465,8 +465,8 @@ static void ath_printrxbuf(const struct
static void ath_printtxbuf(const struct ath_buf *, int);
#endif /* defined(AR_DEBUG) */
-static int ieee80211_debug = 0;
#ifdef AR_DEBUG
+static int ieee80211_debug = 0;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
MODULE_PARM(ieee80211_debug, "i");
#else
@@ -1565,7 +1565,9 @@ ath_vap_delete(struct ieee80211vap *vap)
void
ath_suspend(struct net_device *dev)
{
+#ifdef AR_DEBUG
struct ath_softc *sc = dev->priv;
+#endif
DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
ath_stop(dev);
@@ -1574,7 +1576,9 @@ ath_suspend(struct net_device *dev)
void
ath_resume(struct net_device *dev)
{
+#ifdef AR_DEBUG
struct ath_softc *sc = dev->priv;
+#endif
DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
ath_init(dev);
@@ -4019,7 +4023,9 @@ static void
ath_key_update_begin(struct ieee80211vap *vap)
{
struct net_device *dev = vap->iv_ic->ic_dev;
+#ifdef AR_DEBUG
struct ath_softc *sc = dev->priv;
+#endif
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n");
/*
@@ -4040,7 +4046,9 @@ static void
ath_key_update_end(struct ieee80211vap *vap)
{
struct net_device *dev = vap->iv_ic->ic_dev;
+#ifdef AR_DEBUG
struct ath_softc *sc = dev->priv;
+#endif
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
netif_wake_queue(dev);
@@ -6218,7 +6226,9 @@ ath_recv_mgmt(struct ieee80211vap * vap,
struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf)
{
struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
+#ifdef AR_DEBUG
struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
+#endif
struct ieee80211_node * ni = ni_or_null;
u_int64_t hw_tsf, beacon_tsf;
u_int32_t hw_tu, beacon_tu, intval;
@@ -8382,7 +8392,9 @@ ath_tx_timeout(struct net_device *dev)
static void
ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
{
+#ifdef AR_DEBUG
struct ath_hal *ah = sc->sc_ah;
+#endif
struct ath_buf *bf;
/*
* NB: this assumes output has been stopped and
@@ -11002,6 +11014,7 @@ ath_announce(struct net_device *dev)
strncat(m, b, MLEN);
}
strncat(m, "\n", MLEN);
+#ifdef AR_DEBUG
if (1 /* bootverbose */) {
unsigned int i;
for (i = 0; i <= WME_AC_VO; i++) {
@@ -11014,6 +11027,7 @@ ath_announce(struct net_device *dev)
sc->sc_cabq->axq_qnum);
IPRINTF(sc, "Use hw queue %u for beacons\n", sc->sc_bhalq);
}
+#endif
#undef HAL_MODE_DUALBAND
}
--- a/ath/if_ath_radar.c
+++ b/ath/if_ath_radar.c
@@ -156,7 +156,9 @@ static struct radar_pattern_specificatio
#endif
};
+#ifdef AR_DEBUG
static u_int32_t interval_to_frequency(u_int32_t pri);
+#endif
/* Returns true if radar detection is enabled. */
int ath_radar_is_enabled(struct ath_softc *sc)
@@ -229,7 +231,9 @@ int ath_radar_update(struct ath_softc *s
{
struct ath_hal *ah = sc->sc_ah;
+#ifdef AR_DEBUG
struct net_device *dev = sc->sc_dev;
+#endif
struct ieee80211com *ic = &sc->sc_ic;
int required = 0;
@@ -366,6 +370,7 @@ static struct ath_rp *pulse_prev(struct
#define MR_FAIL_MIN_PERIOD 4
#define MR_FAIL_MAX_PERIOD 5
+#ifdef AR_DEBUG
static const char* get_match_result_desc(u_int32_t code) {
switch (code) {
case MR_MATCH:
@@ -384,6 +389,7 @@ static const char* get_match_result_desc
return "unknown";
}
}
+#endif
static int32_t match_radar(
u_int32_t matched,
@@ -775,7 +781,10 @@ static HAL_BOOL rp_analyse_short_pulse(
struct ath_softc *sc, struct ath_rp *last_pulse,
u_int32_t *index, u_int32_t *pri, u_int32_t *matching_pulses,
u_int32_t *missed_pulses, u_int32_t *noise_pulses)
-{ struct net_device *dev = sc->sc_dev;
+{
+#ifdef AR_DEBUG
+ struct net_device *dev = sc->sc_dev;
+#endif
int i;
int best_index = -1;
unsigned int best_matched = 0;
@@ -1217,6 +1226,7 @@ static HAL_BOOL rp_analyse_short_pulse(
return (-1 != best_index) ? AH_TRUE : AH_FALSE;
}
+#ifdef AR_DEBUG
static u_int32_t interval_to_frequency(u_int32_t interval)
{
/* Calculate BRI from PRI */
@@ -1224,6 +1234,7 @@ static u_int32_t interval_to_frequency(u
/* Round to nearest multiple of 50 */
return frequency + ((frequency % 50) >= 25 ? 50 : 0) - (frequency % 50);
}
+#endif
#ifdef ATH_RADAR_LONG_PULSE
static const char* get_longpulse_desc(int lp) {
@@ -1580,7 +1591,9 @@ void ath_rp_done(struct ath_softc *sc)
void ath_rp_record(struct ath_softc *sc, u_int64_t tsf, u_int8_t rssi,
u_int8_t width, HAL_BOOL is_simulated)
{
+#ifdef AR_DEBUG
struct net_device *dev = sc->sc_dev;
+#endif
struct ath_rp *pulse;
DPRINTF(sc, ATH_DEBUG_DOTHPULSES, "%s: ath_rp_record: "
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -931,7 +931,9 @@ ath_proc_read_nodes(struct ieee80211vap
(struct ieee80211_node_table *) &vap->iv_ic->ic_sta;
unsigned int x = 0;
unsigned int this_tp, this_prob, this_eprob;
+#ifdef AR_DEBUG
struct ath_softc *sc = vap->iv_ic->ic_dev->priv;;
+#endif
IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
--- a/net80211/ieee80211_scan_ap.c
+++ b/net80211/ieee80211_scan_ap.c
@@ -731,6 +731,7 @@ pick_channel(struct ieee80211_scan_state
sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap);
+#ifdef IEEE80211_DEBUG
for (i = 0; i < ss_last; i++) {
int chan = ieee80211_chan2ieee(ic, chans[i].chan);
@@ -742,6 +743,7 @@ pick_channel(struct ieee80211_scan_state
!!IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan,
ic->ic_bsschan));
}
+#endif
best = NULL;
best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */

View File

@ -0,0 +1,536 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -184,7 +184,11 @@ static void ath_recv_mgmt(struct ieee802
struct sk_buff *, int, int, u_int64_t);
static void ath_setdefantenna(struct ath_softc *, u_int);
static struct ath_txq *ath_txq_setup(struct ath_softc *, int, int);
-static void ath_rx_tasklet(TQUEUE_ARG);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+static int ath_rx_poll(struct napi_struct *napi, int budget);
+#else
+static int ath_rx_poll(struct net_device *dev, int *budget);
+#endif
static int ath_hardstart(struct sk_buff *, struct net_device *);
static int ath_mgtstart(struct ieee80211com *, struct sk_buff *);
#ifdef ATH_SUPERG_COMP
@@ -376,6 +380,9 @@ static u_int32_t ath_set_clamped_maxtxpo
u_int32_t new_clamped_maxtxpower);
static u_int32_t ath_get_real_maxtxpower(struct ath_softc *sc);
+static void ath_poll_disable(struct net_device *dev);
+static void ath_poll_enable(struct net_device *dev);
+
/* calibrate every 30 secs in steady state but check every second at first. */
static int ath_calinterval = ATH_SHORT_CALINTERVAL;
static int ath_countrycode = CTRY_DEFAULT; /* country code */
@@ -547,7 +554,6 @@ ath_attach(u_int16_t devid, struct net_d
atomic_set(&sc->sc_txbuf_counter, 0);
- ATH_INIT_TQUEUE(&sc->sc_rxtq, ath_rx_tasklet, dev);
ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet, dev);
ATH_INIT_TQUEUE(&sc->sc_bmisstq, ath_bmiss_tasklet, dev);
ATH_INIT_TQUEUE(&sc->sc_bstucktq, ath_bstuck_tasklet, dev);
@@ -821,6 +827,12 @@ ath_attach(u_int16_t devid, struct net_d
dev->set_mac_address = ath_set_mac_address;
dev->change_mtu = ath_change_mtu;
dev->tx_queue_len = ATH_TXBUF - ATH_TXBUF_MGT_RESERVED;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ netif_napi_add(dev, &sc->sc_napi, ath_rx_poll, 64);
+#else
+ dev->poll = ath_rx_poll;
+ dev->weight = 64;
+#endif
#ifdef USE_HEADERLEN_RESV
dev->hard_header_len += sizeof(struct ieee80211_qosframe) +
sizeof(struct llc) +
@@ -2220,6 +2232,7 @@ ath_intr(int irq, void *dev_id, struct p
(status & HAL_INT_GLOBAL) ? " HAL_INT_GLOBAL" : ""
);
+ sc->sc_isr = status;
status &= sc->sc_imask; /* discard unasked for bits */
/* As soon as we know we have a real interrupt we intend to service,
* we will check to see if we need an initial hardware TSF reading.
@@ -2277,7 +2290,21 @@ ath_intr(int irq, void *dev_id, struct p
}
if (status & (HAL_INT_RX | HAL_INT_RXPHY)) {
ath_uapsd_processtriggers(sc, hw_tsf);
- ATH_SCHEDULE_TQUEUE(&sc->sc_rxtq, &needmark);
+ sc->sc_isr &= ~HAL_INT_RX;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ if (netif_rx_schedule_prep(dev, &sc->sc_napi))
+#else
+ if (netif_rx_schedule_prep(dev))
+#endif
+ {
+ sc->sc_imask &= ~HAL_INT_RX;
+ ath_hal_intrset(ah, sc->sc_imask);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ __netif_rx_schedule(dev, &sc->sc_napi);
+#else
+ __netif_rx_schedule(dev);
+#endif
+ }
}
if (status & HAL_INT_TX) {
#ifdef ATH_SUPERG_DYNTURBO
@@ -2303,6 +2330,11 @@ ath_intr(int irq, void *dev_id, struct p
}
}
#endif
+ /* disable transmit interrupt */
+ sc->sc_isr &= ~HAL_INT_TX;
+ ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_TX);
+ sc->sc_imask &= ~HAL_INT_TX;
+
ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
}
if (status & HAL_INT_BMISS) {
@@ -2515,6 +2547,7 @@ ath_init(struct net_device *dev)
if (sc->sc_tx99 != NULL)
sc->sc_tx99->start(sc->sc_tx99);
#endif
+ ath_poll_enable(dev);
done:
ATH_UNLOCK(sc);
@@ -2555,6 +2588,9 @@ ath_stop_locked(struct net_device *dev)
if (sc->sc_tx99 != NULL)
sc->sc_tx99->stop(sc->sc_tx99);
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ ath_poll_disable(dev);
+#endif
netif_stop_queue(dev); /* XXX re-enabled by ath_newstate */
dev->flags &= ~IFF_RUNNING; /* NB: avoid recursion */
ieee80211_stop_running(ic); /* stop all VAPs */
@@ -4013,12 +4049,47 @@ ath_key_set(struct ieee80211vap *vap, co
return ath_keyset(sc, k, mac, vap->iv_bss);
}
+static void ath_poll_disable(struct net_device *dev)
+{
+ struct ath_softc *sc = dev->priv;
+
+ /*
+ * XXX Using in_softirq is not right since we might
+ * be called from other soft irq contexts than
+ * ath_rx_poll
+ */
+ if (!in_softirq()) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ napi_disable(&sc->sc_napi);
+#else
+ netif_poll_disable(dev);
+#endif
+ }
+}
+
+static void ath_poll_enable(struct net_device *dev)
+{
+ struct ath_softc *sc = dev->priv;
+
+ /* NB: see above */
+ if (!in_softirq()) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ napi_enable(&sc->sc_napi);
+#else
+ netif_poll_enable(dev);
+#endif
+ }
+}
+
+
/*
* Block/unblock tx+rx processing while a key change is done.
* We assume the caller serializes key management operations
* so we only need to worry about synchronization with other
* uses that originate in the driver.
*/
+#define IS_UP(_dev) \
+ (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
static void
ath_key_update_begin(struct ieee80211vap *vap)
{
@@ -4032,14 +4103,9 @@ ath_key_update_begin(struct ieee80211vap
* When called from the rx tasklet we cannot use
* tasklet_disable because it will block waiting
* for us to complete execution.
- *
- * XXX Using in_softirq is not right since we might
- * be called from other soft irq contexts than
- * ath_rx_tasklet.
*/
- if (!in_softirq())
- tasklet_disable(&sc->sc_rxtq);
- netif_stop_queue(dev);
+ if (IS_UP(vap->iv_dev))
+ netif_stop_queue(dev);
}
static void
@@ -4051,9 +4117,9 @@ ath_key_update_end(struct ieee80211vap *
#endif
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
- netif_wake_queue(dev);
- if (!in_softirq()) /* NB: see above */
- tasklet_enable(&sc->sc_rxtq);
+
+ if (IS_UP(vap->iv_dev))
+ netif_wake_queue(dev);
}
/*
@@ -6360,15 +6426,25 @@ ath_setdefantenna(struct ath_softc *sc,
sc->sc_rxotherant = 0;
}
-static void
-ath_rx_tasklet(TQUEUE_ARG data)
+static int
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ath_rx_poll(struct napi_struct *napi, int budget)
+#else
+ath_rx_poll(struct net_device *dev, int *budget)
+#endif
{
#define PA2DESC(_sc, _pa) \
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
- struct net_device *dev = (struct net_device *)data;
- struct ath_buf *bf;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi);
+ struct net_device *dev = sc->sc_dev;
+ u_int rx_limit = budget;
+#else
struct ath_softc *sc = dev->priv;
+ u_int rx_limit = min(dev->quota, *budget);
+#endif
+ struct ath_buf *bf;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc ? sc->sc_ah : NULL;
struct ath_desc *ds;
@@ -6378,8 +6454,10 @@ ath_rx_tasklet(TQUEUE_ARG data)
unsigned int len;
int type;
u_int phyerr;
+ u_int processed = 0, early_stop = 0;
DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n");
+process_rx_again:
do {
bf = STAILQ_FIRST(&sc->sc_rxbuf);
if (bf == NULL) { /* XXX ??? can this happen */
@@ -6403,6 +6481,15 @@ ath_rx_tasklet(TQUEUE_ARG data)
/* NB: never process the self-linked entry at the end */
break;
}
+
+ if (rx_limit-- < 2) {
+ early_stop = 1;
+ break;
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ processed++;
+#endif
+
skb = bf->bf_skb;
if (skb == NULL) {
EPRINTF(sc, "Dropping; buffer contains NULL skbuff.\n");
@@ -6450,6 +6537,7 @@ ath_rx_tasklet(TQUEUE_ARG data)
sc->sc_stats.ast_rx_phyerr++;
phyerr = rs->rs_phyerr & 0x1f;
sc->sc_stats.ast_rx_phy[phyerr]++;
+ goto rx_next;
}
if (rs->rs_status & HAL_RXERR_DECRYPT) {
/*
@@ -6645,9 +6733,39 @@ rx_next:
STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
ATH_RXBUF_UNLOCK_IRQ(sc);
} while (ath_rxbuf_init(sc, bf) == 0);
+ if (!early_stop) {
+ unsigned long flags;
+ /* Check if more data is received while we were
+ * processing the descriptor chain.
+ */
+ local_irq_save(flags);
+ if (sc->sc_isr & HAL_INT_RX) {
+ u_int64_t hw_tsf = ath_hal_gettsf64(ah);
+ sc->sc_isr &= ~HAL_INT_RX;
+ local_irq_restore(flags);
+ ath_uapsd_processtriggers(sc, hw_tsf);
+ goto process_rx_again;
+ }
+ local_irq_restore(flags);
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ netif_rx_complete(dev, napi);
+#else
+ netif_rx_complete(dev);
+ *budget -= processed;
+ dev->quota -= processed;
+#endif
+ sc->sc_imask |= HAL_INT_RX;
+ ath_hal_intrset(ah, sc->sc_imask);
/* rx signal state monitoring */
ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ return processed;
+#else
+ return early_stop;
+#endif
#undef PA2DESC
}
@@ -8298,12 +8416,24 @@ ath_tx_tasklet_q0(TQUEUE_ARG data)
{
struct net_device *dev = (struct net_device *)data;
struct ath_softc *sc = dev->priv;
+ unsigned long flags;
+process_tx_again:
if (txqactive(sc->sc_ah, 0))
ath_tx_processq(sc, &sc->sc_txq[0]);
if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
ath_tx_processq(sc, sc->sc_cabq);
+ local_irq_save(flags);
+ if (sc->sc_isr & HAL_INT_TX) {
+ sc->sc_isr &= ~HAL_INT_TX;
+ local_irq_restore(flags);
+ goto process_tx_again;
+ }
+ sc->sc_imask |= HAL_INT_TX;
+ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+ local_irq_restore(flags);
+
netif_wake_queue(dev);
if (sc->sc_softled)
@@ -8319,7 +8449,9 @@ ath_tx_tasklet_q0123(TQUEUE_ARG data)
{
struct net_device *dev = (struct net_device *)data;
struct ath_softc *sc = dev->priv;
+ unsigned long flags;
+process_tx_again:
/*
* Process each active queue.
*/
@@ -8340,6 +8472,16 @@ ath_tx_tasklet_q0123(TQUEUE_ARG data)
if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum))
ath_tx_processq(sc, sc->sc_uapsdq);
+ local_irq_save(flags);
+ if (sc->sc_isr & HAL_INT_TX) {
+ sc->sc_isr &= ~HAL_INT_TX;
+ local_irq_restore(flags);
+ goto process_tx_again;
+ }
+ sc->sc_imask |= HAL_INT_TX;
+ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+ local_irq_restore(flags);
+
netif_wake_queue(dev);
if (sc->sc_softled)
@@ -8355,13 +8497,25 @@ ath_tx_tasklet(TQUEUE_ARG data)
struct net_device *dev = (struct net_device *)data;
struct ath_softc *sc = dev->priv;
unsigned int i;
+ unsigned long flags;
/* Process each active queue. This includes sc_cabq, sc_xrtq and
* sc_uapsdq */
+process_tx_again:
for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i))
ath_tx_processq(sc, &sc->sc_txq[i]);
+ local_irq_save(flags);
+ if (sc->sc_isr & HAL_INT_TX) {
+ sc->sc_isr &= ~HAL_INT_TX;
+ local_irq_restore(flags);
+ goto process_tx_again;
+ }
+ sc->sc_imask |= HAL_INT_TX;
+ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+ local_irq_restore(flags);
+
netif_wake_queue(dev);
if (sc->sc_softled)
@@ -10296,9 +10450,9 @@ ath_change_mtu(struct net_device *dev, i
dev->mtu = mtu;
if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) {
/* NB: the rx buffers may need to be reallocated */
- tasklet_disable(&sc->sc_rxtq);
+ ath_poll_disable(dev);
error = ath_reset(dev);
- tasklet_enable(&sc->sc_rxtq);
+ ath_poll_enable(dev);
}
ATH_UNLOCK(sc);
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -53,6 +53,10 @@
# include <asm/bitops.h>
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#define irqs_disabled() 0
+#endif
+
/*
* Deduce if tasklets are available. If not then
* fall back to using the immediate work queue.
@@ -616,6 +620,9 @@ struct ath_rp {
struct ath_softc {
struct ieee80211com sc_ic; /* NB: must be first */
struct net_device *sc_dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ struct napi_struct sc_napi;
+#endif
void __iomem *sc_iobase; /* address of the device */
struct semaphore sc_lock; /* dev-level lock */
struct net_device_stats sc_devstats; /* device statistics */
@@ -730,7 +737,6 @@ struct ath_softc {
struct ath_buf *sc_rxbufcur; /* current rx buffer */
u_int32_t *sc_rxlink; /* link ptr in last RX desc */
spinlock_t sc_rxbuflock;
- struct ATH_TQ_STRUCT sc_rxtq; /* rx intr tasklet */
struct ATH_TQ_STRUCT sc_rxorntq; /* rxorn intr tasklet */
u_int8_t sc_defant; /* current default antenna */
u_int8_t sc_rxotherant; /* RXs on non-default antenna */
@@ -745,6 +751,7 @@ struct ath_softc {
u_int sc_txintrperiod; /* tx interrupt batching */
struct ath_txq sc_txq[HAL_NUM_TX_QUEUES];
struct ath_txq *sc_ac2q[WME_NUM_AC]; /* WME AC -> h/w qnum */
+ HAL_INT sc_isr; /* unmasked ISR state */
struct ATH_TQ_STRUCT sc_txtq; /* tx intr tasklet */
u_int8_t sc_grppoll_str[GRPPOLL_RATE_STR_LEN];
struct ath_descdma sc_bdma; /* beacon descriptors */
@@ -858,6 +865,8 @@ typedef void (*ath_callback) (struct ath
#define ATH_TXBUF_LOCK_CHECK(_sc)
#endif
+#define ATH_DISABLE_INTR local_irq_disable
+#define ATH_ENABLE_INTR local_irq_enable
#define ATH_RXBUF_LOCK_INIT(_sc) spin_lock_init(&(_sc)->sc_rxbuflock)
#define ATH_RXBUF_LOCK_DESTROY(_sc)
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -1198,7 +1198,7 @@ ieee80211_deliver_data(struct ieee80211_
/* attach vlan tag */
struct ieee80211_node *ni_tmp = SKB_CB(skb)->ni;
if (vlan_hwaccel_receive_skb(skb, vap->iv_vlgrp, ni->ni_vlan) == NET_RX_DROP) {
- /* If netif_rx dropped the packet because
+ /* If netif_receive_skb dropped the packet because
* device was too busy */
if (ni_tmp != NULL) {
/* node reference was leaked */
@@ -1209,8 +1209,8 @@ ieee80211_deliver_data(struct ieee80211_
skb = NULL; /* SKB is no longer ours */
} else {
struct ieee80211_node *ni_tmp = SKB_CB(skb)->ni;
- if (netif_rx(skb) == NET_RX_DROP) {
- /* If netif_rx dropped the packet because
+ if (netif_receive_skb(skb) == NET_RX_DROP) {
+ /* If netif_receive_skb dropped the packet because
* device was too busy */
if (ni_tmp != NULL) {
/* node reference was leaked */
@@ -2322,8 +2322,8 @@ forward_mgmt_to_app(struct ieee80211vap
skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
ni_tmp = SKB_CB(skb1)->ni;
- if (netif_rx(skb1) == NET_RX_DROP) {
- /* If netif_rx dropped the packet because
+ if (netif_receive_skb(skb1) == NET_RX_DROP) {
+ /* If netif_receive_skb dropped the packet because
* device was too busy */
if (ni_tmp != NULL) {
/* node reference was leaked */
--- a/net80211/ieee80211_monitor.c
+++ b/net80211/ieee80211_monitor.c
@@ -584,8 +584,8 @@ ieee80211_input_monitor(struct ieee80211
skb1->protocol =
__constant_htons(0x0019); /* ETH_P_80211_RAW */
- if (netif_rx(skb1) == NET_RX_DROP) {
- /* If netif_rx dropped the packet because
+ if (netif_receive_skb(skb1) == NET_RX_DROP) {
+ /* If netif_receive_skb dropped the packet because
* device was too busy, reclaim the ref. in
* the skb. */
if (SKB_CB(skb1)->ni != NULL)
--- a/net80211/ieee80211_skb.c
+++ b/net80211/ieee80211_skb.c
@@ -73,7 +73,7 @@
#undef dev_queue_xmit
#undef kfree_skb
#undef kfree_skb_fast
-#undef netif_rx
+#undef netif_receive_skb
#undef pskb_copy
#undef skb_clone
#undef skb_copy
@@ -638,8 +638,8 @@ int vlan_hwaccel_receive_skb_debug(stru
grp, vlan_tag);
}
-int netif_rx_debug(struct sk_buff *skb, const char* func, int line) {
- return netif_rx(untrack_skb(skb, 0, func, line, __func__, __LINE__));
+int netif_receive_skb_debug(struct sk_buff *skb, const char* func, int line) {
+ return netif_receive_skb(untrack_skb(skb, 0, func, line, __func__, __LINE__));
}
struct sk_buff * alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
@@ -760,7 +760,7 @@ struct sk_buff * skb_copy_expand_debug(c
}
EXPORT_SYMBOL(vlan_hwaccel_receive_skb_debug);
-EXPORT_SYMBOL(netif_rx_debug);
+EXPORT_SYMBOL(netif_receive_skb_debug);
EXPORT_SYMBOL(alloc_skb_debug);
EXPORT_SYMBOL(dev_alloc_skb_debug);
EXPORT_SYMBOL(skb_clone_debug);
--- a/net80211/ieee80211_skb.h
+++ b/net80211/ieee80211_skb.h
@@ -116,7 +116,7 @@ int ieee80211_skb_references(void);
int vlan_hwaccel_receive_skb_debug(struct sk_buff *skb,
struct vlan_group *grp, unsigned short vlan_tag,
const char* func, int line);
-int netif_rx_debug(struct sk_buff *skb, const char* func, int line);
+int netif_receive_skb_debug(struct sk_buff *skb, const char* func, int line);
struct sk_buff * alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
const char *func, int line);
struct sk_buff * dev_alloc_skb_debug(unsigned int length,
@@ -151,7 +151,7 @@ struct sk_buff * skb_copy_expand_debug(c
#undef dev_queue_xmit
#undef kfree_skb
#undef kfree_skb_fast
-#undef netif_rx
+#undef netif_receive_skb
#undef pskb_copy
#undef skb_clone
#undef skb_copy
@@ -168,8 +168,8 @@ struct sk_buff * skb_copy_expand_debug(c
skb_copy_expand_debug(_skb, _newheadroom, _newtailroom, _gfp_mask, __func__, __LINE__)
#define vlan_hwaccel_receive_skb(_skb, _grp, _tag) \
vlan_hwaccel_receive_skb_debug(_skb, _grp, _tag, __func__, __LINE__)
-#define netif_rx(_skb) \
- netif_rx_debug(_skb, __func__, __LINE__)
+#define netif_receive_skb(_skb) \
+ netif_receive_skb_debug(_skb, __func__, __LINE__)
#define alloc_skb(_length, _gfp_mask) \
alloc_skb_debug(_length, _gfp_mask, __func__, __LINE__)
#define dev_alloc_skb(_length) \

View File

@ -0,0 +1,168 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -4158,7 +4158,9 @@ ath_calcrxfilter(struct ath_softc *sc)
rfilt |= HAL_RX_FILTER_PROM;
if (ic->ic_opmode == IEEE80211_M_STA ||
sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */
- (sc->sc_nostabeacons) || sc->sc_scanning)
+ (sc->sc_nostabeacons) || sc->sc_scanning ||
+ ((ic->ic_opmode == IEEE80211_M_HOSTAP) &&
+ (ic->ic_protmode != IEEE80211_PROT_NONE)))
rfilt |= HAL_RX_FILTER_BEACON;
if (sc->sc_nmonvaps > 0)
rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -346,11 +346,12 @@ ieee80211_input(struct ieee80211vap * va
bssid = wh->i_addr3;
}
/*
- * Validate the bssid.
+ * Validate the bssid. Let beacons get through though for 11g protection mode.
*/
-#ifdef ATH_SUPERG_XR
if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
- !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
+ !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
+ (subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
+#ifdef ATH_SUPERG_XR
/*
* allow MGT frames to vap->iv_xrvap.
* this will allow roaming between XR and normal vaps
@@ -366,18 +367,14 @@ ieee80211_input(struct ieee80211vap * va
vap->iv_stats.is_rx_wrongbss++;
goto out;
}
- }
#else
- if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
- !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
/* not interested in */
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
bssid, NULL, "%s", "not to bss");
vap->iv_stats.is_rx_wrongbss++;
goto out;
- }
-
#endif
+ }
break;
case IEEE80211_M_WDS:
if (skb->len < sizeof(struct ieee80211_frame_addr4)) {
@@ -3066,7 +3063,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
u_int8_t *frm, *efrm;
u_int8_t *ssid, *rates, *xrates, *suppchan, *wpa, *rsn, *wme, *ath;
u_int8_t rate;
- int reassoc, resp, allocbs = 0;
+ int reassoc, resp, allocbs = 0, has_erp = 0;
u_int8_t qosinfo;
if (ni_or_null == NULL)
@@ -3096,11 +3093,15 @@ ieee80211_recv_mgmt(struct ieee80211vap
* o station mode when associated (to collect state
* updates such as 802.11g slot time), or
* o adhoc mode (to discover neighbors)
+ * o ap mode in protection mode (beacons only)
* Frames otherwise received are discarded.
*/
if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
(vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) ||
- vap->iv_opmode == IEEE80211_M_IBSS)) {
+ (vap->iv_opmode == IEEE80211_M_IBSS) ||
+ ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
+ (vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+ (ic->ic_protmode != IEEE80211_PROT_NONE)))) {
vap->iv_stats.is_rx_mgtdiscard++;
return;
}
@@ -3184,6 +3185,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
break;
}
scan.erp = frm[2];
+ has_erp = 1;
break;
case IEEE80211_ELEMID_RSN:
scan.rsn = frm;
@@ -3421,6 +3423,20 @@ ieee80211_recv_mgmt(struct ieee80211vap
ieee80211_bg_scan(vap);
return;
}
+
+ /* Update AP protection mode when in 11G mode */
+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+ IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
+
+ /* Assume no ERP IE == 11b AP */
+ if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+ !(ic->ic_flags & IEEE80211_F_USEPROT)) {
+
+ ic->ic_flags |= IEEE80211_F_USEPROT;
+ ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ }
+ }
+
/*
* If scanning, just pass information to the scan module.
*/
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -383,10 +383,16 @@ ieee80211_create_ibss(struct ieee80211va
/* Update country ie information */
ieee80211_build_countryie(ic);
- if (IEEE80211_IS_CHAN_HALF(chan))
+ if (IEEE80211_IS_CHAN_HALF(chan)) {
ni->ni_rates = ic->ic_sup_half_rates;
- else if (IEEE80211_IS_CHAN_QUARTER(chan))
+ } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
ni->ni_rates = ic->ic_sup_quarter_rates;
+ }
+
+ if ((vap->iv_flags & IEEE80211_F_PUREG) &&
+ IEEE80211_IS_CHAN_ANYG(chan)) {
+ ieee80211_setpuregbasicrates(&ni->ni_rates);
+ }
(void) ieee80211_sta_join1(PASS_NODE(ni));
}
--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
@@ -595,6 +595,28 @@ static const struct ieee80211_rateset ba
{ 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_TURBO_G (mixed b/g) */
};
+static const struct ieee80211_rateset basicpureg[] = {
+ { 7, {2, 4, 11, 22, 12, 24, 48 } },
+};
+
+/*
+ * Mark basic rates for the 11g rate table based on the pureg setting
+ */
+void
+ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs)
+{
+ int i, j;
+
+ for (i = 0; i < rs->rs_nrates; i++) {
+ rs->rs_rates[i] &= IEEE80211_RATE_VAL;
+ for (j = 0; j < basicpureg[0].rs_nrates; j++)
+ if (basicpureg[0].rs_rates[j] == rs->rs_rates[i]) {
+ rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
+ break;
+ }
+ }
+}
+
/*
* Mark the basic rates for the 11g rate table based on the
* specified mode. For 11b compatibility we mark only 11b
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -708,6 +708,7 @@ int ieee80211_media_setup(struct ieee802
void ieee80211_build_sc_ie(struct ieee80211com *);
void ieee80211_dfs_action(struct ieee80211com *);
void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
+void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
/*
* Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.

View File

@ -0,0 +1,321 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6457,6 +6457,7 @@ ath_rx_poll(struct net_device *dev, int
int type;
u_int phyerr;
u_int processed = 0, early_stop = 0;
+ u_int mic_fail = 0;
DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n");
process_rx_again:
@@ -6558,24 +6559,8 @@ process_rx_again:
}
if (rs->rs_status & HAL_RXERR_MIC) {
sc->sc_stats.ast_rx_badmic++;
- /*
- * Do minimal work required to hand off
- * the 802.11 header for notification.
- */
- /* XXX frag's and QoS frames */
- if (len >= sizeof (struct ieee80211_frame)) {
- bus_dma_sync_single(sc->sc_bdev,
- bf->bf_skbaddr, len,
- BUS_DMA_FROMDEVICE);
-#if 0
-/* XXX revalidate MIC, lookup ni to find VAP */
- ieee80211_notify_michael_failure(ic,
- (struct ieee80211_frame *)skb->data,
- sc->sc_splitmic ?
- rs->rs_keyix - 32 : rs->rs_keyix
- );
-#endif
- }
+ mic_fail = 1;
+ goto rx_accept;
}
/*
* Reject error frames if we have no vaps that
@@ -6614,8 +6599,9 @@ rx_accept:
/*
* Finished monitor mode handling, now reject
* error frames before passing to other vaps
+ * Ignore MIC failures here, as we need to recheck them
*/
- if (rs->rs_status != 0) {
+ if (rs->rs_status & ~(HAL_RXERR_MIC | HAL_RXERR_DECRYPT)) {
ieee80211_dev_kfree_skb(&skb);
goto rx_next;
}
@@ -6623,6 +6609,26 @@ rx_accept:
/* remove the CRC */
skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
+ if (mic_fail) {
+ /* Ignore control frames which are reported with mic error */
+ if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
+ IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
+ goto drop_micfail;
+
+ ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
+
+ if (ni && ni->ni_table) {
+ ieee80211_check_mic(ni, skb);
+ ieee80211_unref_node(&ni);
+ }
+
+drop_micfail:
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ mic_fail = 0;
+ goto rx_next;
+ }
+
/*
* From this point on we assume the frame is at least
* as large as ieee80211_frame_min; verify that.
@@ -6635,6 +6641,7 @@ rx_accept:
goto rx_next;
}
+ /* MIC failure. Drop the packet in any case */
/*
* Normal receive.
*/
--- a/net80211/ieee80211_crypto_ccmp.c
+++ b/net80211/ieee80211_crypto_ccmp.c
@@ -73,7 +73,7 @@ static int ccmp_setkey(struct ieee80211_
static int ccmp_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
static int ccmp_decap(struct ieee80211_key *, struct sk_buff *, int);
static int ccmp_enmic(struct ieee80211_key *, struct sk_buff *, int);
-static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int);
+static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int, int);
static const struct ieee80211_cipher ccmp = {
.ic_name = "AES-CCM",
@@ -314,7 +314,7 @@ ccmp_decap(struct ieee80211_key *k, stru
* Verify and strip MIC from the frame.
*/
static int
-ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
+ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
{
return 1;
}
--- a/net80211/ieee80211_crypto.h
+++ b/net80211/ieee80211_crypto.h
@@ -145,7 +145,7 @@ struct ieee80211_cipher {
int (*ic_encap)(struct ieee80211_key *, struct sk_buff *, u_int8_t);
int (*ic_decap)(struct ieee80211_key *, struct sk_buff *, int);
int (*ic_enmic)(struct ieee80211_key *, struct sk_buff *, int);
- int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int);
+ int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int, int);
};
extern const struct ieee80211_cipher ieee80211_cipher_none;
@@ -163,10 +163,10 @@ struct ieee80211_key *ieee80211_crypto_d
*/
static __inline int
ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
- struct sk_buff *skb, int hdrlen)
+ struct sk_buff *skb, int hdrlen, int force)
{
const struct ieee80211_cipher *cip = k->wk_cipher;
- return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen) : 1);
+ return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen, force) : 1);
}
/*
--- a/net80211/ieee80211_crypto_none.c
+++ b/net80211/ieee80211_crypto_none.c
@@ -52,7 +52,7 @@ static int none_setkey(struct ieee80211_
static int none_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
static int none_decap(struct ieee80211_key *, struct sk_buff *, int);
static int none_enmic(struct ieee80211_key *, struct sk_buff *, int);
-static int none_demic(struct ieee80211_key *, struct sk_buff *, int);
+static int none_demic(struct ieee80211_key *, struct sk_buff *, int, int);
const struct ieee80211_cipher ieee80211_cipher_none = {
.ic_name = "NONE",
@@ -137,7 +137,7 @@ none_enmic(struct ieee80211_key *k, stru
}
static int
-none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
+none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
{
struct ieee80211vap *vap = k->wk_private;
--- a/net80211/ieee80211_crypto_tkip.c
+++ b/net80211/ieee80211_crypto_tkip.c
@@ -57,7 +57,7 @@ static int tkip_setkey(struct ieee80211_
static int tkip_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
static int tkip_enmic(struct ieee80211_key *, struct sk_buff *, int);
static int tkip_decap(struct ieee80211_key *, struct sk_buff *, int);
-static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int);
+static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int, int);
static const struct ieee80211_cipher tkip = {
.ic_name = "TKIP",
@@ -339,7 +339,7 @@ tkip_decap(struct ieee80211_key *k, stru
* Verify and strip MIC from the frame.
*/
static int
-tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen)
+tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen, int force)
{
struct tkip_ctx *ctx = k->wk_private;
struct sk_buff *skb;
@@ -355,7 +355,7 @@ tkip_demic(struct ieee80211_key *k, stru
}
wh = (struct ieee80211_frame *) skb0->data;
/* NB: skb left pointing at last in chain */
- if (k->wk_flags & IEEE80211_KEY_SWMIC) {
+ if ((k->wk_flags & IEEE80211_KEY_SWMIC) || force) {
struct ieee80211vap *vap = ctx->tc_vap;
u8 mic[IEEE80211_WEP_MICLEN];
u8 mic0[IEEE80211_WEP_MICLEN];
--- a/net80211/ieee80211_crypto_wep.c
+++ b/net80211/ieee80211_crypto_wep.c
@@ -54,7 +54,7 @@ static int wep_setkey(struct ieee80211_k
static int wep_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
static int wep_decap(struct ieee80211_key *, struct sk_buff *, int);
static int wep_enmic(struct ieee80211_key *, struct sk_buff *, int);
-static int wep_demic(struct ieee80211_key *, struct sk_buff *, int);
+static int wep_demic(struct ieee80211_key *, struct sk_buff *, int, int);
static const struct ieee80211_cipher wep = {
.ic_name = "WEP",
@@ -244,7 +244,7 @@ wep_decap(struct ieee80211_key *k, struc
* Verify and strip MIC from the frame.
*/
static int
-wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
+wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
{
return 1;
}
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -669,7 +669,7 @@ ieee80211_input(struct ieee80211vap * va
* Next strip any MSDU crypto bits.
*/
if (key != NULL &&
- !ieee80211_crypto_demic(vap, key, skb, hdrspace)) {
+ !ieee80211_crypto_demic(vap, key, skb, hdrspace, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
IEEE80211_NODE_STAT(ni, rx_demicfail);
@@ -4293,6 +4293,47 @@ ath_eth_type_trans(struct sk_buff *skb,
}
#endif
+/*
+ * Process a frame w/ hw detected MIC failure.
+ * The frame will be dropped in any case.
+ */
+void
+ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+
+ struct ieee80211_frame *wh;
+ struct ieee80211_key *key;
+ int hdrspace;
+ struct ieee80211com *ic = vap->iv_ic;
+
+ if (skb->len < sizeof(struct ieee80211_frame_min)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, NULL,
+ "too short (1): len %u", skb->len);
+ vap->iv_stats.is_rx_tooshort++;
+ return;
+ }
+
+ wh = (struct ieee80211_frame *)skb->data;
+
+ hdrspace = ieee80211_hdrspace(ic, wh);
+ key = ieee80211_crypto_decap(ni, skb, hdrspace);
+ if (key == NULL) {
+ /* NB: stats+msgs handled in crypto_decap */
+ IEEE80211_NODE_STAT(ni, rx_wepfail);
+ return;
+ }
+
+ if (!ieee80211_crypto_demic(vap, key, skb, hdrspace, 1)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ ni->ni_macaddr, "data", "%s", "demic error");
+ IEEE80211_NODE_STAT(ni, rx_demicfail);
+ }
+ return;
+}
+EXPORT_SYMBOL(ieee80211_check_mic);
+
#ifdef IEEE80211_DEBUG
/*
* Debugging support.
--- a/net80211/ieee80211_proto.h
+++ b/net80211/ieee80211_proto.h
@@ -90,6 +90,7 @@ int ieee80211_iserp_rateset(struct ieee8
void ieee80211_set11gbasicrates(struct ieee80211_rateset *, enum ieee80211_phymode);
enum ieee80211_phymode ieee80211_get11gbasicrates(struct ieee80211_rateset *);
void ieee80211_send_pspoll(struct ieee80211_node *);
+void ieee80211_check_mic(struct ieee80211_node *, struct sk_buff *);
/*
* Return the size of the 802.11 header for a management or data frame.
--- a/net80211/ieee80211_linux.c
+++ b/net80211/ieee80211_linux.c
@@ -337,8 +337,8 @@ ieee80211_notify_replay_failure(struct i
/* TODO: needed parameters: count, keyid, key type, src address, TSC */
snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,
k->wk_keyix,
- IEEE80211_IS_MULTICAST(wh->i_addr1) ? "broad" : "uni",
- MAC_ADDR(wh->i_addr1));
+ IEEE80211_IS_MULTICAST(wh->i_addr2) ? "broad" : "uni",
+ MAC_ADDR(wh->i_addr2));
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = strlen(buf);
wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -1074,13 +1074,16 @@ ieee80211_encap(struct ieee80211_node *n
cip = (struct ieee80211_cipher *) key->wk_cipher;
ciphdrsize = cip->ic_header;
tailsize += (cip->ic_trailer + cip->ic_miclen);
+
+ /* add the 8 bytes MIC length */
+ if (cip->ic_cipher == IEEE80211_CIPHER_TKIP)
+ pktlen += IEEE80211_WEP_MICLEN;
}
pdusize = vap->iv_fragthreshold - (hdrsize_nopad + ciphdrsize);
fragcnt = *framecnt =
- ((pktlen - (hdrsize_nopad + ciphdrsize)) / pdusize) +
- (((pktlen - (hdrsize_nopad + ciphdrsize)) %
- pdusize == 0) ? 0 : 1);
+ ((pktlen - hdrsize_nopad) / pdusize) +
+ (((pktlen - hdrsize_nopad) % pdusize == 0) ? 0 : 1);
/*
* Allocate sk_buff for each subsequent fragment; First fragment
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -2264,11 +2264,13 @@ ieee80211_node_leave(struct ieee80211_no
/* From this point onwards we can no longer find the node,
* so no more references are generated
*/
- ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
- ieee80211_del_wds_node(nt, ni);
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
- node_table_leave_locked(nt, ni);
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+ if (nt) {
+ ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
+ ieee80211_del_wds_node(nt, ni);
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+ node_table_leave_locked(nt, ni);
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+ }
/*
* If node wasn't previously associated all

View File

@ -0,0 +1,55 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1699,8 +1699,6 @@ ath_uapsd_processtriggers(struct ath_sof
* get to reality. This value is used in monitor mode and by tools like
* Wireshark and Kismet.
*/
- ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
-
ATH_RXBUF_LOCK_IRQ(sc);
if (sc->sc_rxbufcur == NULL)
sc->sc_rxbufcur = STAILQ_FIRST(&sc->sc_rxbuf);
@@ -8975,6 +8973,7 @@ ath_calibrate(unsigned long arg)
sc->sc_curchan.channel);
sc->sc_stats.ast_per_calfail++;
}
+ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
ath_hal_process_noisefloor(ah);
if (isIQdone == AH_TRUE) {
@@ -9043,6 +9042,7 @@ ath_set_channel(struct ieee80211com *ic)
struct ath_softc *sc = dev->priv;
(void) ath_chan_set(sc, ic->ic_curchan);
+ ic->ic_channoise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
/*
* If we are returning to our bss channel then mark state
* so the next recv'd beacon's TSF will be used to sync the
@@ -9311,6 +9311,7 @@ ath_newstate(struct ieee80211vap *vap, e
}
ath_hal_process_noisefloor(ah);
+ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
/*
* Reset rssi stats; maybe not the best place...
*/
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -4358,6 +4358,7 @@ get_sta_info(void *arg, struct ieee80211
si->isi_state = ni->ni_flags;
si->isi_authmode = ni->ni_authmode;
si->isi_rssi = ic->ic_node_getrssi(ni);
+ si->isi_noise = ic->ic_channoise;
si->isi_capinfo = ni->ni_capinfo;
si->isi_athflags = ni->ni_ath_flags;
si->isi_erp = ni->ni_erp;
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -311,6 +311,7 @@ struct ieee80211req_sta_info {
u_int16_t isi_state; /* state flags */
u_int8_t isi_authmode; /* authentication algorithm */
u_int8_t isi_rssi;
+ int8_t isi_noise;
u_int16_t isi_capinfo; /* capabilities */
u_int8_t isi_athflags; /* Atheros capabilities */
u_int8_t isi_erp; /* ERP element */

View File

@ -0,0 +1,11 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1354,7 +1354,7 @@ ath_vap_create(struct ieee80211com *ic,
TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)
id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));
- for (id = 1; id < ath_maxvaps; id++) {
+ for (id = 0; id < ath_maxvaps; id++) {
/* get the first available slot */
if ((id_mask & (1 << id)) == 0) {
ATH_SET_VAP_BSSID(vap->iv_myaddr, id);

View File

@ -0,0 +1,68 @@
--- a/net80211/ieee80211_beacon.c
+++ b/net80211/ieee80211_beacon.c
@@ -542,10 +542,10 @@ ieee80211_beacon_update(struct ieee80211
vap->iv_flags &= ~IEEE80211_F_XRUPDATE;
}
#endif
- if ((ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) &&
+ if ((vap->iv_flags_ext & IEEE80211_FEXT_ERPUPDATE) &&
(bo->bo_erp != NULL)) {
(void)ieee80211_add_erp(bo->bo_erp, ic);
- ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
+ vap->iv_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
}
}
/* if it is a mode change beacon for dynamic turbo case */
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3431,9 +3431,12 @@ ieee80211_recv_mgmt(struct ieee80211vap
/* Assume no ERP IE == 11b AP */
if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
!(ic->ic_flags & IEEE80211_F_USEPROT)) {
+ struct ieee80211vap *tmpvap;
ic->ic_flags |= IEEE80211_F_USEPROT;
- ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+ tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ }
}
}
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -2025,8 +2025,12 @@ ieee80211_node_join_11g(struct ieee80211
}
/* Update ERP element if this is first non ERP station */
- if (ic->ic_nonerpsta == 1)
- ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ if (ic->ic_nonerpsta == 1) {
+ struct ieee80211vap *tmpvap;
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+ tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ }
+ }
} else
ni->ni_flags |= IEEE80211_NODE_ERP;
}
@@ -2229,6 +2233,8 @@ ieee80211_node_leave_11g(struct ieee8021
IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
"non-ERP station leaves, count now %d", ic->ic_nonerpsta);
if (ic->ic_nonerpsta == 0) {
+ struct ieee80211vap *tmpvap;
+
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
"%s: disable use of protection\n", __func__);
ic->ic_flags &= ~IEEE80211_F_USEPROT;
@@ -2240,7 +2246,9 @@ ieee80211_node_leave_11g(struct ieee8021
ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
ic->ic_flags &= ~IEEE80211_F_USEBARKER;
}
- ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+ tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ }
}
}
}

View File

@ -0,0 +1,13 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8689,6 +8689,10 @@ ath_startrecv(struct ath_softc *sc)
sc->sc_rxbufcur = NULL;
+ /* configure bssid mask */
+ if (sc->sc_hasbmask)
+ ath_hal_setbssidmask(ah, sc->sc_bssidmask);
+
bf = STAILQ_FIRST(&sc->sc_rxbuf);
ath_hal_putrxbuf(ah, bf->bf_daddr);
ath_hal_rxena(ah); /* enable recv descriptors */

View File

@ -0,0 +1,38 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1778,17 +1778,14 @@ ath_uapsd_processtriggers(struct ath_sof
* may have occurred in the intervening timeframe. */
bf->bf_channoise = ic->ic_channoise;
- if (rs->rs_status) {
- if ((HAL_RXERR_PHY == rs->rs_status) &&
- (HAL_PHYERR_RADAR ==
- (rs->rs_phyerr & 0x1f)) &&
- (0 == (bf->bf_status &
- ATH_BUFSTATUS_RADAR_DONE))) {
- check_for_radar = 1;
- }
- /* Skip past the error now */
+ if ((HAL_RXERR_PHY == rs->rs_status) &&
+ (HAL_PHYERR_RADAR == (rs->rs_phyerr & 0x1f)) &&
+ (0 == (bf->bf_status & ATH_BUFSTATUS_RADAR_DONE)) &&
+ (ic->ic_flags & IEEE80211_F_DOTH))
+ check_for_radar = 1;
+
+ if (rs->rs_status) /* Skip past the error now */
continue;
- }
/* Prepare wireless header for examination */
bus_dma_sync_single(sc->sc_bdev, bf->bf_skbaddr,
--- a/ath/if_ath_radar.c
+++ b/ath/if_ath_radar.c
@@ -265,7 +265,7 @@ int ath_radar_update(struct ath_softc *s
unsigned int new_rxfilt = old_rxfilt;
ath_hal_intrset(ah, old_ier & ~HAL_INT_GLOBAL);
- if (required) {
+ if ((required) && (ic->ic_flags & IEEE80211_F_DOTH)) {
new_radar |= AR5K_PHY_RADAR_ENABLE;
new_filter |= AR5K_AR5212_PHY_ERR_FIL_RADAR;
new_rxfilt |= (HAL_RX_FILTER_PHYERR |

View File

@ -0,0 +1,19 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -1275,14 +1275,8 @@ ieee80211_decap(struct ieee80211vap *vap
eh->ether_type = ether_type;
if (!ALIGNED_POINTER(skb->data + sizeof(*eh), u_int32_t)) {
- struct sk_buff *tskb;
-
- /* XXX: does this always work? */
- tskb = skb_copy(skb, GFP_ATOMIC);
- if (tskb)
- ieee80211_skb_copy_noderef(skb, tskb);
- ieee80211_dev_kfree_skb(&skb);
- skb = tskb;
+ memmove(skb->data - 2, skb->data, skb->len);
+ skb->data -= 2;
}
return skb;
}

View File

@ -0,0 +1,28 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -9792,7 +9792,9 @@ ath_getchannels(struct net_device *dev,
/*
* Convert HAL channels to ieee80211 ones.
*/
+#ifdef AR_DEBUG
IPRINTF(sc, "HAL returned %d channels.\n", nchan);
+#endif
for (i = 0; i < nchan; i++) {
HAL_CHANNEL *c = &chans[i];
struct ieee80211_channel *ichan = &ic->ic_channels[i];
@@ -9819,6 +9821,7 @@ ath_getchannels(struct net_device *dev,
ic->ic_chan_non_occupy[i].tv_sec = 0;
ic->ic_chan_non_occupy[i].tv_usec = 0;
+#ifdef AR_DEBUG
IPRINTF(sc, "Channel %3d (%4d MHz) Max Tx Power %d dBm%s "
"[%d hw %d reg] Flags%s%s%s%s%s%s%s%s%s%s%s%s%"
"s%s%s%s%s%s%s%s%s%s%s%s\n",
@@ -9907,6 +9910,7 @@ ath_getchannels(struct net_device *dev,
(c->privFlags & 0x0080 ?
" PF & (1 << 7)" : "")
);
+#endif
}
ic->ic_nchans = nchan;
kfree(chans);

View File

@ -0,0 +1,40 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8438,8 +8438,6 @@ process_tx_again:
ath_hal_intrset(sc->sc_ah, sc->sc_imask);
local_irq_restore(flags);
- netif_wake_queue(dev);
-
if (sc->sc_softled)
ath_led_event(sc, ATH_LED_TX);
}
@@ -8486,8 +8484,6 @@ process_tx_again:
ath_hal_intrset(sc->sc_ah, sc->sc_imask);
local_irq_restore(flags);
- netif_wake_queue(dev);
-
if (sc->sc_softled)
ath_led_event(sc, ATH_LED_TX);
}
@@ -8520,8 +8516,6 @@ process_tx_again:
ath_hal_intrset(sc->sc_ah, sc->sc_imask);
local_irq_restore(flags);
- netif_wake_queue(dev);
-
if (sc->sc_softled)
ath_led_event(sc, ATH_LED_TX);
}
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -1132,7 +1132,7 @@ ieee80211_deliver_data(struct ieee80211_
(vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0) {
struct sk_buff *skb1 = NULL;
- if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
+ if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
/* Create a SKB for the BSS to send out. */
skb1 = skb_copy(skb, GFP_ATOMIC);
if (skb1)

View File

@ -0,0 +1,166 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -397,6 +397,7 @@ static int countrycode = -1;
static int maxvaps = -1;
static int outdoor = -1;
static int xchanmode = -1;
+static int beacon_cal = 1;
static const char *hal_status_desc[] = {
"No error",
@@ -422,6 +423,7 @@ static struct notifier_block ath_event_b
};
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+MODULE_PARM(beacon_cal, "i");
MODULE_PARM(countrycode, "i");
MODULE_PARM(maxvaps, "i");
MODULE_PARM(outdoor, "i");
@@ -434,6 +436,7 @@ MODULE_PARM(autocreate, "s");
MODULE_PARM(ratectl, "s");
#else
#include <linux/moduleparam.h>
+module_param(beacon_cal, int, 0600);
module_param(countrycode, int, 0600);
module_param(maxvaps, int, 0600);
module_param(outdoor, int, 0600);
@@ -2600,7 +2603,8 @@ ath_stop_locked(struct net_device *dev)
}
if (!sc->sc_invalid) {
del_timer_sync(&sc->sc_dfs_cac_timer);
- del_timer_sync(&sc->sc_cal_ch);
+ if (!sc->sc_beacon_cal)
+ del_timer_sync(&sc->sc_cal_ch);
}
ath_draintxq(sc);
if (!sc->sc_invalid) {
@@ -2617,6 +2621,20 @@ ath_stop_locked(struct net_device *dev)
return 0;
}
+static void ath_set_beacon_cal(struct ath_softc *sc, int val)
+{
+ if (sc->sc_beacon_cal == !!val)
+ return;
+
+ if (val) {
+ del_timer_sync(&sc->sc_cal_ch);
+ } else {
+ sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+ add_timer(&sc->sc_cal_ch);
+ }
+ sc->sc_beacon_cal = !!val && beacon_cal;
+}
+
/*
* Stop the device, grabbing the top-level lock to protect
* against concurrent entry through ath_init (which can happen
@@ -2742,6 +2760,12 @@ ath_reset(struct net_device *dev)
HAL_STATUS status;
/*
+ * XXX: starting the calibration too early seems to lead to
+ * problems with the beacons.
+ */
+ sc->sc_lastcal = jiffies;
+
+ /*
* Convert to a HAL channel description with the flags
* constrained to reflect the current operating mode.
*/
@@ -5154,6 +5178,10 @@ ath_beacon_send(struct ath_softc *sc, in
"Invoking ath_hal_txstart with sc_bhalq: %d\n",
sc->sc_bhalq);
ath_hal_txstart(ah, sc->sc_bhalq);
+ if (sc->sc_beacon_cal && (jiffies > sc->sc_lastcal + (ath_calinterval * HZ))) {
+ sc->sc_cal_ch.expires = jiffies + msecs_to_jiffies(10);
+ add_timer(&sc->sc_cal_ch);
+ }
sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */
}
@@ -5403,6 +5431,7 @@ ath_beacon_config(struct ath_softc *sc,
ath_hal_beacontimers(ah, &bs);
sc->sc_imask |= HAL_INT_BMISS;
ath_hal_intrset(ah, sc->sc_imask);
+ ath_set_beacon_cal(sc, 0);
} else {
ath_hal_intrset(ah, 0);
if (reset_tsf)
@@ -5414,8 +5443,11 @@ ath_beacon_config(struct ath_softc *sc,
*/
intval |= HAL_BEACON_ENA;
sc->sc_imask |= HAL_INT_SWBA;
+ ath_set_beacon_cal(sc, 1);
ath_beaconq_config(sc);
- }
+ } else
+ ath_set_beacon_cal(sc, 0);
+
#ifdef ATH_SUPERG_DYNTURBO
ath_beacon_dturbo_config(vap, intval &
~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA));
@@ -8879,6 +8911,9 @@ ath_chan_set(struct ath_softc *sc, struc
/* Enter DFS wait period */
mod_timer(&sc->sc_dfs_cac_timer,
jiffies + (sc->sc_dfs_cac_period * HZ));
+
+ /* This is a good time to start a calibration */
+ ath_set_beacon_cal(sc, 1);
}
/*
* re configure beacons when it is a turbo mode switch.
@@ -8988,8 +9023,11 @@ ath_calibrate(unsigned long arg)
sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
isIQdone ? "done" : "not done");
- sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
- add_timer(&sc->sc_cal_ch);
+ sc->sc_lastcal = jiffies;
+ if (!sc->sc_beacon_cal) {
+ sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+ add_timer(&sc->sc_cal_ch);
+ }
}
static void
@@ -9096,7 +9134,8 @@ ath_newstate(struct ieee80211vap *vap, e
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate]);
- del_timer(&sc->sc_cal_ch); /* periodic calibration timer */
+ if (!sc->sc_beacon_cal)
+ del_timer(&sc->sc_cal_ch); /* periodic calibration timer */
ath_hal_setledstate(ah, leds[nstate]); /* set LED */
netif_stop_queue(dev); /* before we do anything else */
@@ -9321,7 +9360,8 @@ ath_newstate(struct ieee80211vap *vap, e
"VAP -> DFSWAIT_PENDING \n");
/* start calibration timer with a really small value
* 1/10 sec */
- mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
+ if (!sc->sc_beacon_cal)
+ mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
/* wake the receiver */
netif_wake_queue(dev);
/* don't do the other usual stuff... */
@@ -9364,7 +9404,7 @@ done:
error = avp->av_newstate(vap, nstate, arg);
/* Finally, start any timers. */
- if (nstate == IEEE80211_S_RUN) {
+ if (nstate == IEEE80211_S_RUN && !sc->sc_beacon_cal) {
/* start periodic recalibration timer */
mod_timer(&sc->sc_cal_ch, jiffies + (ath_calinterval * HZ));
}
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -778,6 +778,8 @@ struct ath_softc {
struct ieee80211vap **sc_bslot; /* beacon xmit slots */
int sc_bnext; /* next slot for beacon xmit */
+ int sc_beacon_cal; /* use beacon timer for calibration */
+ u_int64_t sc_lastcal; /* last time the calibration was performed */
struct timer_list sc_cal_ch; /* calibration timer */
HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */

View File

@ -0,0 +1,36 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -3320,17 +3320,18 @@ ath_hardstart(struct sk_buff *skb, struc
* without affecting any other bridge ports. */
if (skb_cloned(skb)) {
/* Remember the original SKB so we can free up our references */
- struct sk_buff *skb_orig = skb;
- skb = skb_copy(skb, GFP_ATOMIC);
- if (skb == NULL) {
+ struct sk_buff *skb_new;
+ skb_new = skb_copy(skb, GFP_ATOMIC);
+ if (skb_new == NULL) {
DPRINTF(sc, ATH_DEBUG_XMIT,
"Dropping; skb_copy failure.\n");
/* No free RAM, do not requeue! */
goto hardstart_fail;
}
- ieee80211_skb_copy_noderef(skb_orig, skb);
- ieee80211_dev_kfree_skb(&skb_orig);
- }
+ ieee80211_skb_copy_noderef(skb, skb_new);
+ ieee80211_dev_kfree_skb(&skb);
+ skb = skb_new;
+ }
eh = (struct ether_header *)skb->data;
#ifdef ATH_SUPERG_FF
@@ -3601,6 +3602,8 @@ ath_mgtstart(struct ieee80211com *ic, st
sc->sc_stats.ast_tx_mgmt++;
return 0;
bad:
+ if (skb)
+ ieee80211_dev_kfree_skb(&skb);
ath_return_txbuf(sc, &bf);
return error;
}

View File

@ -0,0 +1,11 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8922,7 +8922,7 @@ ath_chan_set(struct ath_softc *sc, struc
* re configure beacons when it is a turbo mode switch.
* HW seems to turn off beacons during turbo mode switch.
*/
- if (sc->sc_beacons && tswitch && !sc->sc_dfs_cac)
+ if (sc->sc_beacons && !sc->sc_dfs_cac)
ath_beacon_config(sc, NULL);
/*
* Re-enable interrupts.

View File

@ -0,0 +1,15 @@
--- a/net80211/ieee80211_scan_ap.c
+++ b/net80211/ieee80211_scan_ap.c
@@ -783,12 +783,6 @@ pick_channel(struct ieee80211_scan_state
/* break the loop as the subsequent chans won't be
* better */
break;
-
- if (!IEEE80211_ARE_CHANS_SAME_MODE(c->chan,
- ic->ic_bsschan))
- /* break the loop as the subsequent chans won't be
- * better */
- break;
}
if (sta_assoc != 0) {

View File

@ -0,0 +1,12 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -950,6 +950,9 @@ ieee80211_input_all(struct ieee80211com
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
struct sk_buff *skb1;
+ if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ continue;
+
if (TAILQ_NEXT(vap, iv_next) != NULL) {
skb1 = skb_copy(skb, GFP_ATOMIC);
if (skb1 == NULL) {

View File

@ -0,0 +1,98 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1307,6 +1307,7 @@ ath_vap_create(struct ieee80211com *ic,
vap->iv_key_set = ath_key_set;
vap->iv_key_update_begin = ath_key_update_begin;
vap->iv_key_update_end = ath_key_update_end;
+ vap->iv_maxrateindex = 0;
if (sc->sc_default_ieee80211_debug) {
/* User specified defaults for new VAPs were provided, so
* use those (only). */
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -622,8 +622,12 @@ ath_rate_ctl_reset(struct ath_softc *sc,
return;
}
sn->static_rate_ndx = -1;
+ if (vap->iv_maxrateindex == 0 || ni->ni_rates.rs_nrates <= 0
+ || vap->iv_maxrateindex > ni->ni_rates.rs_nrates)
+ sn->num_rates = ni->ni_rates.rs_nrates;
+ else
+ sn->num_rates = vap->iv_maxrateindex;
- sn->num_rates = ni->ni_rates.rs_nrates;
for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
sn->rs_rateattempts [x] = 0;
sn->rs_thisprob [x] = 0;
--- a/ath_rate/sample/sample.c
+++ b/ath_rate/sample/sample.c
@@ -835,7 +835,12 @@ ath_rate_ctl_reset(struct ath_softc *sc,
}
sn->static_rate_ndx = -1;
- sn->num_rates = ni->ni_rates.rs_nrates;
+ if (vap->iv_maxrateindex == 0 || ni->ni_rates.rs_nrates <= 0
+ || vap->iv_maxrateindex > ni->ni_rates.rs_nrates)
+ sn->num_rates = ni->ni_rates.rs_nrates;
+ else
+ sn->num_rates = vap->iv_maxrateindex;
+
for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -641,6 +641,7 @@ enum {
FCC requires 30m, so that is the default. */
IEEE80211_PARAM_BEACON_MISS_THRESH = 73, /* Beacon miss threshold (in beacons) */
IEEE80211_PARAM_BEACON_MISS_THRESH_MS = 74, /* Beacon miss threshold (in ms) */
+ IEEE80211_PARAM_MAXRATE = 75, /* Maximum rate (by table index) */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -281,6 +281,7 @@ struct ieee80211vap {
struct ieee80211_spy iv_spy; /* IWSPY support */
struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
u_int32_t app_filter; /* filters which management frames are forwarded to app */
+ u_int iv_maxrateindex;
};
/* Debug functions need the defintion of struct ieee80211vap because iv_debug
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2839,6 +2839,12 @@ ieee80211_ioctl_setparam(struct net_devi
else
ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
break;
+ case IEEE80211_PARAM_MAXRATE:
+ if (value > 0)
+ vap->iv_maxrateindex = value;
+ else
+ vap->iv_maxrateindex = 0;
+ break;
#ifdef ATH_REVERSE_ENGINEERING
case IEEE80211_PARAM_DUMPREGS:
ieee80211_dump_registers(dev, info, w, extra);
@@ -3174,6 +3180,9 @@ ieee80211_ioctl_getparam(struct net_devi
else
param[0] = 0;
break;
+ case IEEE80211_PARAM_MAXRATE:
+ param[0] = vap->iv_maxrateindex;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -5610,6 +5619,10 @@ static const struct iw_priv_args ieee802
0, IW_PRIV_TYPE_APPIEBUF, "getiebuf" },
{ IEEE80211_IOCTL_FILTERFRAME,
IW_PRIV_TYPE_FILTER , 0, "setfilter" },
+ {IEEE80211_PARAM_MAXRATE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxrate"},
+ {IEEE80211_PARAM_MAXRATE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxrate"},
#ifdef ATH_REVERSE_ENGINEERING
/*

View File

@ -0,0 +1,114 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1308,6 +1308,7 @@ ath_vap_create(struct ieee80211com *ic,
vap->iv_key_update_begin = ath_key_update_begin;
vap->iv_key_update_end = ath_key_update_end;
vap->iv_maxrateindex = 0;
+ vap->iv_minrateindex = 0;
if (sc->sc_default_ieee80211_debug) {
/* User specified defaults for new VAPs were provided, so
* use those (only). */
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -638,9 +638,15 @@ ath_rate_ctl_reset(struct ath_softc *sc,
sn->rs_succ_hist [x] = 0;
sn->rs_att_hist [x] = 0;
sn->rs_this_tp [x] = 0;
-
+ if (vap->iv_minrateindex && vap->iv_minrateindex<ni->ni_rates.rs_nrates)
+ {
+ int idx = vap->iv_minrateindex;
+ sn->rates[x].rate = ni->ni_rates.rs_rates[idx] & IEEE80211_RATE_VAL;
+ sn->rates[x].rix = sc->sc_rixmap[sn->rates[idx].rate];
+ }else{
sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
+ }
if (sn->rates[x].rix == 0xff) {
DPRINTF(sc, "%s: %s ignore bogus rix at %d\n",
dev_info, __func__, x);
@@ -649,7 +655,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
sn->rates[x].shortPreambleRateCode =
rt->info[sn->rates[x].rix].rateCode |
- rt->info[sn->rates[x].rix].shortPreamble;
+ rt->info[sn->rates[x].rix].shortPreamble;
}
ath_fill_sample_table(sn);
--- a/ath_rate/sample/sample.c
+++ b/ath_rate/sample/sample.c
@@ -842,8 +842,15 @@ ath_rate_ctl_reset(struct ath_softc *sc,
sn->num_rates = vap->iv_maxrateindex;
for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
- sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
- sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
+ if (vap->iv_minrateindex && vap->iv_minrateindex<ni->ni_rates.rs_nrates)
+ {
+ int idx = vap->iv_minrateindex;
+ sn->rates[x].rate = ni->ni_rates.rs_rates[idx] & IEEE80211_RATE_VAL;
+ sn->rates[x].rix = sc->sc_rixmap[sn->rates[idx].rate];
+ }else{
+ sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+ sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
+ }
if (sn->rates[x].rix == 0xff) {
DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %u\n",
dev_info, __func__, x);
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -642,6 +642,7 @@ enum {
IEEE80211_PARAM_BEACON_MISS_THRESH = 73, /* Beacon miss threshold (in beacons) */
IEEE80211_PARAM_BEACON_MISS_THRESH_MS = 74, /* Beacon miss threshold (in ms) */
IEEE80211_PARAM_MAXRATE = 75, /* Maximum rate (by table index) */
+ IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -282,6 +282,7 @@ struct ieee80211vap {
struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
u_int32_t app_filter; /* filters which management frames are forwarded to app */
u_int iv_maxrateindex;
+ u_int iv_minrateindex;
};
/* Debug functions need the defintion of struct ieee80211vap because iv_debug
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2845,6 +2845,12 @@ ieee80211_ioctl_setparam(struct net_devi
else
vap->iv_maxrateindex = 0;
break;
+ case IEEE80211_PARAM_MINRATE:
+ if (value > 0)
+ vap->iv_minrateindex = value;
+ else
+ vap->iv_minrateindex = 0;
+ break;
#ifdef ATH_REVERSE_ENGINEERING
case IEEE80211_PARAM_DUMPREGS:
ieee80211_dump_registers(dev, info, w, extra);
@@ -3183,6 +3189,9 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_MAXRATE:
param[0] = vap->iv_maxrateindex;
break;
+ case IEEE80211_PARAM_MINRATE:
+ param[0] = vap->iv_minrateindex;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -5623,6 +5632,10 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxrate"},
{IEEE80211_PARAM_MAXRATE,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxrate"},
+ {IEEE80211_PARAM_MINRATE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
+ {IEEE80211_PARAM_MINRATE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
#ifdef ATH_REVERSE_ENGINEERING
/*

View File

@ -0,0 +1,263 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -3239,7 +3239,6 @@ ath_hardstart(struct sk_buff *skb, struc
struct ath_softc *sc = dev->priv;
struct ieee80211_node *ni = NULL;
struct ath_buf *bf = NULL;
- struct ether_header *eh;
ath_bufhead bf_head;
struct ath_buf *tbf, *tempbf;
struct sk_buff *tskb;
@@ -3251,6 +3250,7 @@ ath_hardstart(struct sk_buff *skb, struc
*/
int requeue = 0;
#ifdef ATH_SUPERG_FF
+ struct ether_header *eh;
unsigned int pktlen;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_node *an;
@@ -3316,27 +3316,9 @@ ath_hardstart(struct sk_buff *skb, struc
requeue = 1;
goto hardstart_fail;
}
-#endif
- /* If the skb data is shared, we will copy it so we can strip padding
- * without affecting any other bridge ports. */
- if (skb_cloned(skb)) {
- /* Remember the original SKB so we can free up our references */
- struct sk_buff *skb_new;
- skb_new = skb_copy(skb, GFP_ATOMIC);
- if (skb_new == NULL) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "Dropping; skb_copy failure.\n");
- /* No free RAM, do not requeue! */
- goto hardstart_fail;
- }
- ieee80211_skb_copy_noderef(skb, skb_new);
- ieee80211_dev_kfree_skb(&skb);
- skb = skb_new;
- }
eh = (struct ether_header *)skb->data;
-#ifdef ATH_SUPERG_FF
/* NB: use this lock to protect an->an_tx_ffbuf (and txq->axq_stageq)
* in athff_can_aggregate() call too. */
ATH_TXQ_LOCK_IRQ(txq);
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -283,7 +283,7 @@ ieee80211_hardstart(struct sk_buff *skb,
* normal vap. */
if (vap->iv_xrvap && (ni == vap->iv_bss) &&
vap->iv_xrvap->iv_sta_assoc) {
- struct sk_buff *skb1 = skb_copy(skb, GFP_ATOMIC);
+ struct sk_buff *skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1) {
memset(SKB_CB(skb1), 0, sizeof(struct ieee80211_cb));
#ifdef IEEE80211_DEBUG_REFCNT
@@ -566,7 +566,7 @@ ieee80211_skbhdr_adjust(struct ieee80211
struct ieee80211_key *key, struct sk_buff *skb, int ismulticast)
{
/* XXX pre-calculate per node? */
- int need_headroom = LLC_SNAPFRAMELEN + hdrsize + IEEE80211_ADDR_LEN;
+ int need_headroom = LLC_SNAPFRAMELEN + hdrsize;
int need_tailroom = 0;
#ifdef ATH_SUPERG_FF
int isff = ATH_FF_MAGIC_PRESENT(skb);
@@ -608,109 +608,56 @@ ieee80211_skbhdr_adjust(struct ieee80211
need_tailroom += cip->ic_miclen;
}
- if (skb_shared(skb)) {
- /* Take our own reference to the node in the clone */
- ieee80211_ref_node(SKB_CB(skb)->ni);
- /* Unshare the node, decrementing users in the old skb */
- skb = skb_unshare(skb, GFP_ATOMIC);
- }
+ need_headroom -= skb_headroom(skb);
+ if (isff)
+ need_tailroom -= skb_tailroom(skb2);
+ else
+ need_tailroom -= skb_tailroom(skb);
+
+ if (need_headroom < 0)
+ need_headroom = 0;
+ if (need_tailroom < 0)
+ need_tailroom = 0;
-#ifdef ATH_SUPERG_FF
- if (isff) {
- if (skb == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot unshare for encapsulation\n",
- __func__);
- vap->iv_stats.is_tx_nobuf++;
- ieee80211_dev_kfree_skb(&skb2);
+ if (skb_cloned(skb) || (need_headroom > 0) ||
+ (!isff && (need_tailroom > 0))) {
- return NULL;
+ if (pskb_expand_head(skb, need_headroom, need_tailroom, GFP_ATOMIC)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+ "%s: cannot expand storage (tail)\n", __func__);
+ goto error;
}
+ }
- /* first skb header */
- if (skb_headroom(skb) < need_headroom) {
- struct sk_buff *tmp = skb;
- skb = skb_realloc_headroom(skb, need_headroom);
- if (skb == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot expand storage (head1)\n",
- __func__);
- vap->iv_stats.is_tx_nobuf++;
- ieee80211_dev_kfree_skb(&skb2);
- return NULL;
- } else
- ieee80211_skb_copy_noderef(tmp, skb);
- ieee80211_dev_kfree_skb(&tmp);
- /* NB: cb[] area was copied, but not next ptr. must do that
- * prior to return on success. */
- }
+#ifdef ATH_SUPERG_FF
+ if (isff) {
+ inter_headroom -= skb_headroom(skb2);
+ if (inter_headroom < 0)
+ inter_headroom = 0;
+ if ((skb_cloned(skb2) ||
+ (inter_headroom > 0) || (need_tailroom > 0))) {
- /* second skb with header and tail adjustments possible */
- if (skb_tailroom(skb2) < need_tailroom) {
- int n = 0;
- if (inter_headroom > skb_headroom(skb2))
- n = inter_headroom - skb_headroom(skb2);
- if (pskb_expand_head(skb2, n,
- need_tailroom - skb_tailroom(skb2), GFP_ATOMIC)) {
- ieee80211_dev_kfree_skb(&skb2);
+ if (pskb_expand_head(skb2, inter_headroom,
+ need_tailroom, GFP_ATOMIC)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot expand storage (tail2)\n",
- __func__);
- vap->iv_stats.is_tx_nobuf++;
- /* this shouldn't happen, but don't send first ff either */
- ieee80211_dev_kfree_skb(&skb);
+ "%s: cannot expand storage (tail)\n", __func__);
+ goto error;
}
- } else if (skb_headroom(skb2) < inter_headroom) {
- struct sk_buff *tmp = skb2;
-
- skb2 = skb_realloc_headroom(skb2, inter_headroom);
- if (skb2 == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot expand storage (head2)\n",
- __func__);
- vap->iv_stats.is_tx_nobuf++;
- /* this shouldn't happen, but don't send first ff either */
- ieee80211_dev_kfree_skb(&skb);
- skb = NULL;
- } else
- ieee80211_skb_copy_noderef(tmp, skb);
- ieee80211_dev_kfree_skb(&tmp);
- }
- if (skb) {
- skb->next = skb2;
}
- return skb;
+ skb->next = skb2;
}
#endif /* ATH_SUPERG_FF */
- if (skb == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot unshare for encapsulation\n", __func__);
- vap->iv_stats.is_tx_nobuf++;
- } else if (skb_tailroom(skb) < need_tailroom) {
- int n = 0;
- if (need_headroom > skb_headroom(skb))
- n = need_headroom - skb_headroom(skb);
- if (pskb_expand_head(skb, n, need_tailroom -
- skb_tailroom(skb), GFP_ATOMIC)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot expand storage (tail)\n", __func__);
- vap->iv_stats.is_tx_nobuf++;
- ieee80211_dev_kfree_skb(&skb);
- }
- } else if (skb_headroom(skb) < need_headroom) {
- struct sk_buff *tmp = skb;
- skb = skb_realloc_headroom(skb, need_headroom);
- /* Increment reference count after copy */
- if (skb == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: cannot expand storage (head)\n", __func__);
- vap->iv_stats.is_tx_nobuf++;
- } else
- ieee80211_skb_copy_noderef(tmp, skb);
- ieee80211_dev_kfree_skb(&tmp);
- }
return skb;
+
+error:
+ vap->iv_stats.is_tx_nobuf++;
+ ieee80211_dev_kfree_skb(&skb);
+#ifdef ATH_SUPERG_FF
+ if (skb2)
+ ieee80211_dev_kfree_skb(&skb2);
+#endif
+ return NULL;
}
#define KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none)
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -204,7 +204,6 @@ ieee80211_input(struct ieee80211vap * va
struct ieee80211_frame *wh;
struct ieee80211_key *key;
struct ether_header *eh;
- struct sk_buff *skb2;
#ifdef ATH_SUPERG_FF
struct llc *llc;
#endif
@@ -244,20 +243,6 @@ ieee80211_input(struct ieee80211vap * va
vap->iv_stats.is_rx_tooshort++;
goto out;
}
- /* Clone the SKB... we assume somewhere in this driver that we 'own'
- * the skbuff passed into hard start and we do a lot of messing with it
- * but bridges under some cases will not clone for the first pass of skb
- * to a bridge port, but will then clone for subsequent ones. This is
- * odd behavior but it means that if we have trashed the skb we are given
- * then other ports get clones of the residual garbage.
- */
- if ((skb2 = skb_copy(skb, GFP_ATOMIC)) == NULL) {
- vap->iv_devstats.tx_dropped++;
- goto out;
- }
- ieee80211_skb_copy_noderef(skb, skb2);
- ieee80211_dev_kfree_skb(&skb);
- skb = skb2;
/*
* Bit of a cheat here, we use a pointer for a 3-address
@@ -738,7 +723,7 @@ ieee80211_input(struct ieee80211vap * va
/* ether_type must be length as FF frames are always LLC/SNAP encap'd */
frame_len = ntohs(eh_tmp->ether_type);
- skb1 = skb_copy(skb, GFP_ATOMIC);
+ skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1 == NULL)
goto err;
ieee80211_skb_copy_noderef(skb, skb1);
@@ -1137,7 +1122,7 @@ ieee80211_deliver_data(struct ieee80211_
if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
/* Create a SKB for the BSS to send out. */
- skb1 = skb_copy(skb, GFP_ATOMIC);
+ skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1)
SKB_CB(skb1)->ni = ieee80211_ref_node(vap->iv_bss);
}

View File

@ -0,0 +1,34 @@
Merged from madwifi trunk r3551, r3552
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8253,6 +8253,17 @@ ath_tx_processq(struct ath_softc *sc, st
goto bf_fail;
}
+ /* We make sure we don't remove the TX descriptor on
+ * which the HW is pointing since it contains the
+ * ds_link field, except if this is the last TX
+ * descriptor in the queue */
+
+ if ((txq->axq_depth > 1) &&
+ (bf->bf_daddr == ath_hal_gettxbuf(ah, txq->axq_qnum))) {
+ ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
+ goto bf_fail;
+ }
+
ATH_TXQ_REMOVE_HEAD(txq, bf_list);
ATH_TXQ_UNLOCK_IRQ(txq);
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -586,7 +586,8 @@ struct ath_vap {
} while (0)
#define ATH_TXQ_REMOVE_HEAD(_tq, _field) do { \
STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
- (_tq)->axq_depth--; \
+ if (--(_tq)->axq_depth <= 0) \
+ (_tq)->axq_link = NULL; \
} while (0)
/* move buffers from MCASTQ to CABQ */
#define ATH_TXQ_MOVE_MCASTQ(_tqs,_tqd) do { \

View File

@ -0,0 +1,11 @@
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -475,7 +475,7 @@ ath_rate_tx_complete(struct ath_softc *s
/* 'tries' is the total number of times we have endeavoured to
* send this packet, and is a sum of the #attempts at each
* level in the multi-rate retry chain */
- tries = ts->ts_shortretry + ts->ts_longretry + 1;
+ tries = ts->ts_longretry + 1;
if (sn->num_rates <= 0) {
DPRINTF(sc, "%s: " MAC_FMT " %s no rates yet\n", dev_info,

View File

@ -0,0 +1,80 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8103,6 +8103,7 @@ ath_tx_start(struct net_device *dev, str
ath_hal_setupxtxdesc(sc->sc_ah, ds, mrr.rate1, mrr.retries1,
mrr.rate2, mrr.retries2,
mrr.rate3, mrr.retries3);
+ bf->rcflags = mrr.privflags;
}
#ifndef ATH_SUPERG_FF
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -446,6 +446,7 @@ struct ath_buf {
u_int16_t bf_flags; /* tx descriptor flags */
u_int64_t bf_tsf;
int16_t bf_channoise;
+ unsigned int rcflags;
#ifdef ATH_SUPERG_FF
/* XXX: combine this with bf_skbaddr if it ever changes to accommodate
* multiple segments.
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -333,15 +333,19 @@ ath_rate_findrate(struct ath_softc *sc,
if (sn->static_rate_ndx >= 0) {
ndx = sn->static_rate_ndx;
} else {
+ int delta;
sn->packet_count++;
sn->random_n = (sn->a * sn->random_n) + sn->b;
offset = sn->random_n & 0xf;
- if ((((100 * sn->sample_count) / (sn->sample_count + sn->packet_count)) < ath_lookaround_rate) && (offset < 2)) {
+ delta = (sn->packet_count * ath_lookaround_rate / 100) - sn->sample_count;
+ if ((delta > 0) && (offset < 2)) {
sn->sample_count++;
sn->is_sampling = 1;
if (sn->packet_count >= 10000) {
sn->sample_count = 0;
sn->packet_count = 0;
+ } else if (delta > sn->num_rates * 2) {
+ sn->sample_count += ((delta - sn->num_rates * 2) * ath_lookaround_rate) / 100;
}
/* Don't look for slowest rate (i.e. slowest
@@ -398,11 +402,14 @@ ath_rate_get_mrr(struct ath_softc *sc, s
if (sn->num_rates <= 0)
return;
+ mrr->privflags = sn->is_sampling;
if (sn->is_sampling) {
sn->is_sampling = 0;
- if (sn->rs_sample_rate_slower)
+ if (sn->rs_sample_rate_slower) {
rc1 = sn->rs_sample_rate;
- else
+ if (sn->sample_count > 0)
+ sn->sample_count--;
+ } else
rc1 = sn->max_tp_rate;
} else {
rc1 = sn->max_tp_rate2;
@@ -525,6 +532,9 @@ ath_rate_tx_complete(struct ath_softc *s
if (tries <= tries1)
return;
+ if (bf->rcflags)
+ sn->sample_count++;
+
if (tries2 < 0)
return;
tries = tries - tries1;
--- a/net80211/ieee80211_rate.h
+++ b/net80211/ieee80211_rate.h
@@ -87,6 +87,7 @@ struct ieee80211_mrr {
int retries2;
int rate3;
int retries3;
+ int privflags;
};
struct ieee80211_rate_ops {

View File

@ -0,0 +1,135 @@
--- a/net80211/ieee80211.c
+++ b/net80211/ieee80211.c
@@ -333,7 +333,9 @@ ieee80211_ifattach(struct ieee80211com *
IEEE80211_MS_TO_TU(IEEE80211_BMISSTHRESH_DEFAULT_MS),
ic->ic_lintval), ic->ic_lintval);
}
-
+ ic->ic_protmode_timeout = IEEE80211_PROTMODE_TIMEOUT;
+ ic->ic_protmode_rssi = IEEE80211_PROTMODE_RSSITHR;
+
IEEE80211_LOCK_INIT(ic, "ieee80211com");
IEEE80211_VAPS_LOCK_INIT(ic, "ieee80211com_vaps");
TAILQ_INIT(&ic->ic_vaps);
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3411,14 +3411,18 @@ ieee80211_recv_mgmt(struct ieee80211vap
IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
/* Assume no ERP IE == 11b AP */
- if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
- !(ic->ic_flags & IEEE80211_F_USEPROT)) {
+ if ((!has_erp || (has_erp &&
+ (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+ (rssi > ic->ic_protmode_rssi)) {
struct ieee80211vap *tmpvap;
- ic->ic_flags |= IEEE80211_F_USEPROT;
- TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
- tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ if (!(ic->ic_flags & IEEE80211_F_USEPROT)) {
+ ic->ic_flags |= IEEE80211_F_USEPROT;
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+ tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ }
}
+ ic->ic_protmode_lasttrig = jiffies;
}
}
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -643,6 +643,8 @@ enum {
IEEE80211_PARAM_BEACON_MISS_THRESH_MS = 74, /* Beacon miss threshold (in ms) */
IEEE80211_PARAM_MAXRATE = 75, /* Maximum rate (by table index) */
IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */
+ IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
+ IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -128,6 +128,9 @@
#define IEEE80211_APPIE_MAX 1024
+#define IEEE80211_PROTMODE_RSSITHR 15 /* default rssi threshold for protection mode trigger */
+#define IEEE80211_PROTMODE_TIMEOUT 30 /* timeout for keeping protection mode alive */
+
#define IEEE80211_PWRCONSTRAINT_VAL(ic) \
(((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \
(ic)->ic_bsschan->ic_maxregpower - (ic)->ic_curchanmaxpwr : 0)
@@ -324,6 +327,9 @@ struct ieee80211com {
u_int16_t ic_newtxpowlimit; /* tx power limit to change to (in 0.5 dBm) */
u_int16_t ic_uapsdmaxtriggers; /* max triggers that could arrive */
u_int8_t ic_coverageclass; /* coverage class */
+ u_int8_t ic_protmode_rssi; /* rssi threshold for protection mode */
+ u_int64_t ic_protmode_lasttrig; /* last trigger for protection mode */
+ u_int16_t ic_protmode_timeout; /* protection mode timeout */
/* Channel state:
*
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2312,6 +2312,12 @@ ieee80211_ioctl_setparam(struct net_devi
IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
retv = ENETRESET;
break;
+ case IEEE80211_PARAM_PROTMODE_TIMEOUT:
+ ic->ic_protmode_timeout = value;
+ break;
+ case IEEE80211_PARAM_PROTMODE_RSSI:
+ ic->ic_protmode_rssi = value;
+ break;
case IEEE80211_PARAM_MCASTCIPHER:
if ((vap->iv_caps & cipher2cap(value)) == 0 &&
!ieee80211_crypto_available(vap, value))
@@ -2955,6 +2961,12 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_PROTMODE:
param[0] = ic->ic_protmode;
break;
+ case IEEE80211_PARAM_PROTMODE_TIMEOUT:
+ param[0] = ic->ic_protmode_timeout;
+ break;
+ case IEEE80211_PARAM_PROTMODE_RSSI:
+ param[0] = ic->ic_protmode_rssi;
+ break;
case IEEE80211_PARAM_MCASTCIPHER:
param[0] = rsn->rsn_mcastcipher;
break;
@@ -5346,6 +5358,14 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protmode" },
{ IEEE80211_PARAM_PROTMODE,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protmode" },
+ { IEEE80211_PARAM_PROTMODE_RSSI,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protrssi" },
+ { IEEE80211_PARAM_PROTMODE_RSSI,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protrssi" },
+ { IEEE80211_PARAM_PROTMODE_TIMEOUT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "prottime" },
+ { IEEE80211_PARAM_PROTMODE_TIMEOUT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_prottime" },
{ IEEE80211_PARAM_MCASTCIPHER,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcastcipher" },
{ IEEE80211_PARAM_MCASTCIPHER,
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -1877,6 +1877,17 @@ ieee80211_node_timeout(unsigned long arg
ieee80211_scan_timeout(ic);
ieee80211_timeout_stations(&ic->ic_sta);
+ if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+ (ic->ic_protmode_lasttrig + ic->ic_protmode_timeout * HZ <
+ jiffies)) {
+ struct ieee80211vap *tmpvap;
+
+ /* expire protection mode */
+ ic->ic_flags &= ~IEEE80211_F_USEPROT;
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+ tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ }
+ }
ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ;
add_timer(&ic->ic_inact);

View File

@ -0,0 +1,99 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -10276,11 +10276,11 @@ ath_setcurmode(struct ath_softc *sc, enu
sc->sc_currates = rt;
sc->sc_curmode = mode;
/*
- * All protection frames are transmitted at 2Mb/s for
- * 11g, otherwise at 1Mb/s.
+ * All protection frames are transmitted at 11Mb/s for
+ * 11g, otherwise at 2Mb/s.
* XXX select protection rate index from rate table.
*/
- sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 1 : 0);
+ sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 3 : 1);
/* rate index used to send mgt frames */
sc->sc_minrateix = 0;
}
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -272,6 +272,10 @@ static inline struct net_device *_alloc_
#define AES_ICV_FIELD_SIZE 8 /* AES ICV field size */
#define EXT_IV_FIELD_SIZE 4 /* ext IV field size */
+/* This is what the HAL uses by default for 11a+g */
+#define ATH_DEFAULT_CWMIN 15
+#define ATH_DEFAULT_CWMAX 1023
+
/* XR specific macros */
#define XR_DEFAULT_GRPPOLL_RATE_STR "0.25 1 1 3 3 6 6 20"
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -197,7 +197,7 @@ calc_usecs_unicast_packet(struct ath_sof
unsigned int x = 0, tt = 0;
unsigned int cix = rt->info[rix].controlRate;
int rts = 0, cts = 0;
- int cw = WIFI_CW_MIN;
+ int cw = ATH_DEFAULT_CWMIN;
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
@@ -281,7 +281,7 @@ calc_usecs_unicast_packet(struct ath_sof
tt += (long_retries + 1) * ath_hal_computetxtime(sc->sc_ah, rt, length,
rix, AH_TRUE);
for (x = 0; x <= short_retries + long_retries; x++) {
- cw = MIN(WIFI_CW_MAX, (cw + 1) * 2);
+ cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
tt += (t_slot * cw / 2);
}
return tt;
--- a/ath_rate/minstrel/minstrel.h
+++ b/ath_rate/minstrel/minstrel.h
@@ -180,14 +180,6 @@ struct minstrel_node {
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
-#if 0
-#define WIFI_CW_MIN 31
-#define WIFI_CW_MAX 1023
-#else
-#define WIFI_CW_MIN 3
-#define WIFI_CW_MAX 10
-#endif
-
/*
* Definitions for pulling the rate and trie counts from
* a 5212 h/w descriptor. These Don't belong here; the
--- a/ath_rate/sample/sample.c
+++ b/ath_rate/sample/sample.c
@@ -170,7 +170,7 @@ calc_usecs_unicast_packet(struct ath_sof
struct ieee80211com *ic = &sc->sc_ic;
unsigned int tt = 0;
unsigned int x;
- unsigned int cw = WIFI_CW_MIN;
+ unsigned int cw = ATH_DEFAULT_CWMIN;
unsigned int cix = rt->info[rix].controlRate;
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
@@ -254,7 +254,7 @@ calc_usecs_unicast_packet(struct ath_sof
tt += (long_retries+1)*ath_hal_computetxtime(sc->sc_ah, rt, length,
rix, AH_TRUE);
for (x = 0; x <= short_retries + long_retries; x++) {
- cw = MIN(WIFI_CW_MAX, (cw + 1) * 2);
+ cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
tt += (t_slot * cw / 2);
}
return tt;
--- a/ath_rate/sample/sample.h
+++ b/ath_rate/sample/sample.h
@@ -106,9 +106,6 @@ struct sample_node {
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
-#define WIFI_CW_MIN 31
-#define WIFI_CW_MAX 1023
-
/*
* Definitions for pulling the rate and trie counts from
* a 5212 h/w descriptor. These Don't belong here; the

View File

@ -0,0 +1,38 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -2723,6 +2723,9 @@ ar_device(int devid)
static int
ath_set_ack_bitrate(struct ath_softc *sc, int high)
{
+ if (!sc->sc_ackrate_override)
+ return 0;
+
if (ar_device(sc->devid) == 5212 || ar_device(sc->devid) == 5213) {
/* set ack to be sent at low bit-rate */
/* registers taken from the OpenBSD 5212 HAL */
@@ -10791,8 +10794,13 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
break;
#endif
case ATH_ACKRATE:
- sc->sc_ackrate = val;
- ath_set_ack_bitrate(sc, sc->sc_ackrate);
+ if (val == -1)
+ sc->sc_ackrate_override = 0;
+ else {
+ sc->sc_ackrate_override = 1;
+ sc->sc_ackrate = val;
+ ath_set_ack_bitrate(sc, sc->sc_ackrate);
+ }
break;
case ATH_RP:
ath_rp_record(sc,
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -681,6 +681,7 @@ struct ath_softc {
unsigned int sc_devstopped:1; /* stopped due to of no tx bufs */
unsigned int sc_stagbeacons:1; /* use staggered beacons */
unsigned int sc_dfswait:1; /* waiting on channel for radar detect */
+ unsigned int sc_ackrate_override:1; /* override ack rate */
unsigned int sc_ackrate:1; /* send acks at high bitrate */
unsigned int sc_dfs_cac:1; /* waiting on channel for radar detect */
unsigned int sc_hasintmit:1; /* Interference mitigation */

View File

@ -0,0 +1,12 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8864,8 +8864,7 @@ ath_chan_set(struct ath_softc *sc, struc
* needed to do the reset with chanchange = AH_FALSE in order
* to receive traffic when peforming high velocity channel
* changes. */
- if (!ath_hal_reset(ah, sc->sc_opmode, &hchan, AH_TRUE, &status) ||
- !ath_hal_reset(ah, sc->sc_opmode, &hchan, AH_FALSE, &status)) {
+ if (!ath_hal_reset(ah, sc->sc_opmode, &hchan, AH_TRUE, &status)) {
EPRINTF(sc, "Unable to reset channel %u (%u MHz) "
"flags 0x%x '%s' (HAL status %u)\n",
ieee80211_chan2ieee(ic, chan), chan->ic_freq,

View File

@ -0,0 +1,11 @@
--- a/ath/if_ath_ahb.c
+++ b/ath/if_ath_ahb.c
@@ -245,6 +245,8 @@ init_ath_wmac(u_int16_t devid, u_int16_t
num_activesc++;
/* Ready to process interrupts */
+ sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
+ sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
sc->aps_sc.sc_invalid = 0;
return 0;

View File

@ -0,0 +1,904 @@
--- a/net80211/ieee80211_scan_sta.c
+++ b/net80211/ieee80211_scan_sta.c
@@ -317,147 +317,6 @@ found:
#undef ISPROBE
}
-static struct ieee80211_channel *
-find11gchannel(struct ieee80211com *ic, int i, int freq)
-{
- struct ieee80211_channel *c;
- int j;
-
- /*
- * The normal ordering in the channel list is b channel
- * immediately followed by g so optimize the search for
- * this. We'll still do a full search just in case.
- */
- for (j = i+1; j < ic->ic_nchans; j++) {
- c = &ic->ic_channels[j];
- if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
- return c;
- }
- for (j = 0; j < i; j++) {
- c = &ic->ic_channels[j];
- if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
- return c;
- }
- return NULL;
-}
-static const u_int chanflags[] = {
- IEEE80211_CHAN_B, /* IEEE80211_MODE_AUTO */
- IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
- IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
- IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
- IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */
- IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */
-};
-
-static void
-add_channels(struct ieee80211com *ic,
- struct ieee80211_scan_state *ss,
- enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
-{
- struct ieee80211_channel *c, *cg;
- u_int modeflags;
- int i;
-
- KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
- modeflags = chanflags[mode];
- for (i = 0; i < nfreq; i++) {
- c = ieee80211_find_channel(ic, freq[i], modeflags);
- if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
- continue;
- if (mode == IEEE80211_MODE_AUTO) {
- /*
- * XXX special-case 11b/g channels so we select
- * the g channel if both are present.
- */
- if (IEEE80211_IS_CHAN_B(c) &&
- (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
- c = cg;
- }
- if (ss->ss_last >= IEEE80211_SCAN_MAX)
- break;
- ss->ss_chans[ss->ss_last++] = c;
- }
-}
-
-static const u_int16_t rcl1[] = /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */
-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
-static const u_int16_t rcl2[] = /* 4 MKK channels: 34, 38, 42, 46 */
-{ 5170, 5190, 5210, 5230 };
-static const u_int16_t rcl3[] = /* 2.4Ghz ch: 1,6,11,7,13 */
-{ 2412, 2437, 2462, 2442, 2472 };
-static const u_int16_t rcl4[] = /* 5 FCC channel: 149, 153, 161, 165 */
-{ 5745, 5765, 5785, 5805, 5825 };
-static const u_int16_t rcl7[] = /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */
-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
-static const u_int16_t rcl8[] = /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
-static const u_int16_t rcl9[] = /* 2.4Ghz ch: 14 */
-{ 2484 };
-static const u_int16_t rcl10[] = /* Added Korean channels 2312-2372 */
-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
-static const u_int16_t rcl11[] = /* Added Japan channels in 4.9/5.0 spectrum */
-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
-#ifdef ATH_TURBO_SCAN
-static const u_int16_t rcl5[] = /* 3 static turbo channels */
-{ 5210, 5250, 5290 };
-static const u_int16_t rcl6[] = /* 2 static turbo channels */
-{ 5760, 5800 };
-static const u_int16_t rcl6x[] = /* 4 FCC3 turbo channels */
-{ 5540, 5580, 5620, 5660 };
-static const u_int16_t rcl12[] = /* 2.4Ghz Turbo channel 6 */
-{ 2437 };
-static const u_int16_t rcl13[] = /* dynamic Turbo channels */
-{ 5200, 5240, 5280, 5765, 5805 };
-#endif /* ATH_TURBO_SCAN */
-
-struct scanlist {
- u_int16_t mode;
- u_int16_t count;
- const u_int16_t *list;
-};
-
-#define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAX
-#define X(a) .count = sizeof(a)/sizeof(a[0]), .list = a
-
-static const struct scanlist staScanTable[] = {
- { IEEE80211_MODE_11B, X(rcl3) },
- { IEEE80211_MODE_11A, X(rcl1) },
- { IEEE80211_MODE_11A, X(rcl2) },
- { IEEE80211_MODE_11B, X(rcl8) },
- { IEEE80211_MODE_11B, X(rcl9) },
- { IEEE80211_MODE_11A, X(rcl4) },
-#ifdef ATH_TURBO_SCAN
- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl5) },
- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl6) },
- { IEEE80211_MODE_TURBO_A, X(rcl6x) },
- { IEEE80211_MODE_TURBO_A, X(rcl13) },
-#endif /* ATH_TURBO_SCAN */
- { IEEE80211_MODE_11A, X(rcl7) },
- { IEEE80211_MODE_11B, X(rcl10) },
- { IEEE80211_MODE_11A, X(rcl11) },
-#ifdef ATH_TURBO_SCAN
- { IEEE80211_MODE_TURBO_G, X(rcl12) },
-#endif /* ATH_TURBO_SCAN */
- { .list = NULL }
-};
-
-#undef X
-
-static int
-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
-{
- int i;
-
- for (; scan->list != NULL; scan++) {
- for (i = 0; i < scan->count; i++)
- if (scan->list[i] == c->ic_freq)
- return 1;
- }
- return 0;
-}
-
/*
* Start a station-mode scan by populating the channel list.
*/
@@ -466,81 +325,14 @@ sta_start(struct ieee80211_scan_state *s
{
struct ieee80211com *ic = vap->iv_ic;
struct sta_table *st = ss->ss_priv;
- const struct scanlist *scan;
enum ieee80211_phymode mode;
struct ieee80211_channel *c;
int i;
ss->ss_last = 0;
- /*
- * Use the table of ordered channels to construct the list
- * of channels for scanning. Any channels in the ordered
- * list not in the master list will be discarded.
- */
- for (scan = staScanTable; scan->list != NULL; scan++) {
- mode = scan->mode;
- if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
- /*
- * If a desired mode was specified, scan only
- * channels that satisfy that constraint.
- */
- if (vap->iv_des_mode != mode) {
- /*
- * The scan table marks 2.4Ghz channels as b
- * so if the desired mode is 11g, then use
- * the 11b channel list but upgrade the mode.
- */
- if (vap->iv_des_mode != IEEE80211_MODE_11G ||
- mode != IEEE80211_MODE_11B)
- continue;
- mode = IEEE80211_MODE_11G; /* upgrade */
- }
- } else {
- /*
- * This lets ieee80211_scan_add_channels
- * upgrade an 11b channel to 11g if available.
- */
- if (mode == IEEE80211_MODE_11B)
- mode = IEEE80211_MODE_AUTO;
- }
- /* XR does not operate on turbo channels */
- if ((vap->iv_flags & IEEE80211_F_XR) &&
- (mode == IEEE80211_MODE_TURBO_A ||
- mode == IEEE80211_MODE_TURBO_G))
- continue;
- /*
- * Add the list of the channels; any that are not
- * in the master channel list will be discarded.
- */
- add_channels(ic, ss, mode, scan->list, scan->count);
- }
-
- /*
- * Add the channels from the ic (from HAL) that are not present
- * in the staScanTable.
- */
- for (i = 0; i < ic->ic_nchans; i++) {
- c = &ic->ic_channels[i];
- /*
- * scan dynamic turbo channels in normal mode.
- */
- if (IEEE80211_IS_CHAN_DTURBO(c))
- continue;
- mode = ieee80211_chan2mode(c);
- if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
- /*
- * If a desired mode was specified, scan only
- * channels that satisfy that constraint.
- */
- if (vap->iv_des_mode != mode)
- continue;
-
- }
- if (!checktable(staScanTable, c))
- ss->ss_chans[ss->ss_last++] = c;
- }
-
+ ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
ss->ss_next = 0;
+
/* XXX tunables */
/*
* The scanner will stay on station for ss_maxdwell ms (using a
@@ -749,17 +541,7 @@ match_bss(struct ieee80211vap *vap,
fail = 0;
if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan)))
fail |= 0x01;
- /*
- * NB: normally the desired mode is used to construct
- * the channel list, but it's possible for the scan
- * cache to include entries for stations outside this
- * list so we check the desired mode here to weed them
- * out.
- */
- if (vap->iv_des_mode != IEEE80211_MODE_AUTO &&
- (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
- chanflags[vap->iv_des_mode])
- fail |= 0x01;
+
if (vap->iv_opmode == IEEE80211_M_IBSS) {
if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
fail |= 0x02;
@@ -1168,78 +950,6 @@ static const struct ieee80211_scanner st
.scan_default = ieee80211_sta_join,
};
-/*
- * Start an adhoc-mode scan by populating the channel list.
- */
-static int
-adhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
-{
- struct ieee80211com *ic = vap->iv_ic;
- struct sta_table *st = ss->ss_priv;
- const struct scanlist *scan;
- enum ieee80211_phymode mode;
-
- ss->ss_last = 0;
- /*
- * Use the table of ordered channels to construct the list
- * of channels for scanning. Any channels in the ordered
- * list not in the master list will be discarded.
- */
- for (scan = staScanTable; scan->list != NULL; scan++) {
- mode = scan->mode;
- if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
- /*
- * If a desired mode was specified, scan only
- * channels that satisfy that constraint.
- */
- if (vap->iv_des_mode != mode) {
- /*
- * The scan table marks 2.4Ghz channels as b
- * so if the desired mode is 11g, then use
- * the 11b channel list but upgrade the mode.
- */
- if (vap->iv_des_mode != IEEE80211_MODE_11G ||
- mode != IEEE80211_MODE_11B)
- continue;
- mode = IEEE80211_MODE_11G; /* upgrade */
- }
- } else {
- /*
- * This lets ieee80211_scan_add_channels
- * upgrade an 11b channel to 11g if available.
- */
- if (mode == IEEE80211_MODE_11B)
- mode = IEEE80211_MODE_AUTO;
- }
- /* XR does not operate on turbo channels */
- if ((vap->iv_flags & IEEE80211_F_XR) &&
- (mode == IEEE80211_MODE_TURBO_A ||
- mode == IEEE80211_MODE_TURBO_G))
- continue;
- /*
- * Add the list of the channels; any that are not
- * in the master channel list will be discarded.
- */
- add_channels(ic, ss, mode, scan->list, scan->count);
- }
- ss->ss_next = 0;
- /* XXX tunables */
- ss->ss_mindwell = msecs_to_jiffies(200); /* 200ms */
- ss->ss_maxdwell = msecs_to_jiffies(200); /* 200ms */
-
-#ifdef IEEE80211_DEBUG
- if (ieee80211_msg_scan(vap)) {
- printk("%s: scan set ", vap->iv_dev->name);
- ieee80211_scan_dump_channels(ss);
- printk(" dwell min %ld max %ld\n",
- ss->ss_mindwell, ss->ss_maxdwell);
- }
-#endif /* IEEE80211_DEBUG */
-
- st->st_newscan = 1;
-
- return 0;
-}
/*
* Select a channel to start an adhoc network on.
@@ -1405,7 +1115,7 @@ static const struct ieee80211_scanner ad
.scan_name = "default",
.scan_attach = sta_attach,
.scan_detach = sta_detach,
- .scan_start = adhoc_start,
+ .scan_start = sta_start,
.scan_restart = sta_restart,
.scan_cancel = sta_cancel,
.scan_end = adhoc_pick_bss,
--- a/net80211/ieee80211.c
+++ b/net80211/ieee80211.c
@@ -278,6 +278,11 @@ ieee80211_ifattach(struct ieee80211com *
("channel with bogus ieee number %u", c->ic_ieee));
setbit(ic->ic_chan_avail, c->ic_ieee);
+ if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)
+ c->ic_scanflags |= IEEE80211_NOSCAN_SET;
+ else
+ c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
+
/* Identify mode capabilities. */
if (IEEE80211_IS_CHAN_A(c))
ic->ic_modecaps |= 1 << IEEE80211_MODE_11A;
@@ -1447,10 +1452,6 @@ ieee80211_media_change(struct net_device
vap->iv_fixed_rate = newrate; /* fixed TX rate */
error = -ENETRESET;
}
- if (vap->iv_des_mode != newmode) {
- vap->iv_des_mode = newmode; /* desired PHY mode */
- error = -ENETRESET;
- }
return error;
}
EXPORT_SYMBOL(ieee80211_media_change);
--- a/net80211/_ieee80211.h
+++ b/net80211/_ieee80211.h
@@ -132,6 +132,11 @@ enum ieee80211_scanmode {
IEEE80211_SCAN_FIRST = 2, /* take first suitable candidate */
};
+enum ieee80211_scanflags {
+ IEEE80211_NOSCAN_DEFAULT = (1 << 0),
+ IEEE80211_NOSCAN_SET = (1 << 1),
+};
+
/*
* Channels are specified by frequency and attributes.
*/
@@ -142,6 +147,7 @@ struct ieee80211_channel {
int8_t ic_maxregpower; /* maximum regulatory tx power in dBm */
int8_t ic_maxpower; /* maximum tx power in dBm */
int8_t ic_minpower; /* minimum tx power in dBm */
+ u_int8_t ic_scanflags;
};
#define IEEE80211_CHAN_MAX 255
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -555,6 +555,7 @@ struct ieee80211req_scan_result {
#define IEEE80211_IOCTL_WDSADDMAC (SIOCIWFIRSTPRIV+26)
#define IEEE80211_IOCTL_WDSDELMAC (SIOCIWFIRSTPRIV+28)
#define IEEE80211_IOCTL_KICKMAC (SIOCIWFIRSTPRIV+30)
+#define IEEE80211_IOCTL_SETSCANLIST (SIOCIWFIRSTPRIV+31)
enum {
IEEE80211_WMMPARAMS_CWMIN = 1,
--- a/net80211/ieee80211_scan_ap.c
+++ b/net80211/ieee80211_scan_ap.c
@@ -105,11 +105,6 @@ struct scan_entry {
};
struct ap_state {
- unsigned int as_vap_desired_mode; /* Used for channel selection,
- * vap->iv_des_mode */
- unsigned int as_required_mode; /* Used for channel selection,
- * filtered version of
- * as_vap_desired_mode */
int as_maxrssi[IEEE80211_CHAN_MAX]; /* Used for channel selection */
/* These fields are just for scan caching for returning responses to
@@ -129,131 +124,7 @@ struct ap_state {
static int ap_flush(struct ieee80211_scan_state *);
static void action_tasklet(IEEE80211_TQUEUE_ARG);
-static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic,
- int i, int freq);
-static const u_int chanflags[] = {
- IEEE80211_CHAN_B, /* IEEE80211_MODE_AUTO */
- IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
- IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
- IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
- IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode
- * look for AP in
- * normal channel
- */
- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */
- IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */
-};
-
-static const u_int16_t rcl1[] = /* 8 FCC channel: 52, 56, 60, 64,
- * 36, 40, 44, 48 */
-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
-static const u_int16_t rcl2[] = /* 4 MKK channels: 34, 38, 42, 46 */
-{ 5170, 5190, 5210, 5230 };
-static const u_int16_t rcl3[] = /* 2.4Ghz ch: 1,6,11,7,13 */
-{ 2412, 2437, 2462, 2442, 2472 };
-static const u_int16_t rcl4[] = /* 5 FCC channel: 149, 153, 161, 165 */
-{ 5745, 5765, 5785, 5805, 5825 };
-static const u_int16_t rcl7[] = /* 11 ETSI channel: 100, 104, 108, 112,
- * 116, 120, 124, 128,
- * 132, 136, 140 */
-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
-static const u_int16_t rcl8[] = /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
-static const u_int16_t rcl9[] = /* 2.4Ghz ch: 14 */
-{ 2484 };
-static const u_int16_t rcl10[] = /* Added Korean channels 2312-2372 */
-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
-static const u_int16_t rcl11[] = /* Added Japan channels in 4.9/5.0 spectrum */
-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
-#ifdef ATH_TURBO_SCAN
-static const u_int16_t rcl5[] = /* 3 static turbo channels */
-{ 5210, 5250, 5290 };
-static const u_int16_t rcl6[] = /* 2 static turbo channels */
-{ 5760, 5800 };
-static const u_int16_t rcl6x[] = /* 4 FCC3 turbo channels */
-{ 5540, 5580, 5620, 5660 };
-static const u_int16_t rcl12[] = /* 2.4Ghz Turbo channel 6 */
-{ 2437 };
-static const u_int16_t rcl13[] = /* dynamic Turbo channels */
-{ 5200, 5240, 5280, 5765, 5805 };
-#endif /* ATH_TURBO_SCAN */
-
-struct scanlist {
- u_int16_t mode;
- u_int16_t count;
- const u_int16_t *list;
-};
-
-#define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAX
-#define X(a) .count = ARRAY_SIZE(a), .list = a
-
-static const struct scanlist staScanTable[] = {
- { IEEE80211_MODE_11B, X(rcl3) },
- { IEEE80211_MODE_11A, X(rcl1) },
- { IEEE80211_MODE_11A, X(rcl2) },
- { IEEE80211_MODE_11B, X(rcl8) },
- { IEEE80211_MODE_11B, X(rcl9) },
- { IEEE80211_MODE_11A, X(rcl4) },
-#ifdef ATH_TURBO_SCAN
- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl5) },
- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl6) },
- { IEEE80211_MODE_TURBO_A, X(rcl6x) },
- { IEEE80211_MODE_TURBO_A, X(rcl13) },
-#endif /* ATH_TURBO_SCAN */
- { IEEE80211_MODE_11A, X(rcl7) },
- { IEEE80211_MODE_11B, X(rcl10) },
- { IEEE80211_MODE_11A, X(rcl11) },
-#ifdef ATH_TURBO_SCAN
- { IEEE80211_MODE_TURBO_G, X(rcl12) },
-#endif /* ATH_TURBO_SCAN */
- { .list = NULL }
-};
-
-#undef X
-/* This function must be invoked with locks acquired */
-static void
-add_channels(struct ieee80211com *ic,
- struct ieee80211_scan_state *ss,
- enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
-{
- struct ieee80211_channel *c, *cg;
- u_int modeflags;
- int i;
-
- KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
- modeflags = chanflags[mode];
- for (i = 0; i < nfreq; i++) {
- c = ieee80211_find_channel(ic, freq[i], modeflags);
- if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
- continue;
- if (mode == IEEE80211_MODE_AUTO) {
- /* XXX special-case 11b/g channels so we select
- * the g channel if both are present. */
- if (IEEE80211_IS_CHAN_B(c) &&
- (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
- c = cg;
- }
- if (ss->ss_last >= IEEE80211_SCAN_MAX)
- break;
- ss->ss_chans[ss->ss_last++] = c;
- }
-}
-
-/* This function must be invoked with locks acquired */
-static int
-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
-{
- int i;
-
- for (; scan->list != NULL; scan++) {
- for (i = 0; i < scan->count; i++)
- if (scan->list[i] == c->ic_freq)
- return 1;
- }
- return 0;
-}
/*
* Attach prior to any scanning work.
@@ -327,29 +198,6 @@ saveie(u_int8_t **iep, const u_int8_t *i
ieee80211_saveie(iep, ie);
}
-/* This function must be invoked with locks acquired */
-static struct ieee80211_channel *
-find11gchannel(struct ieee80211com *ic, int i, int freq)
-{
- struct ieee80211_channel *c;
- int j;
-
- /* The normal ordering in the channel list is b channel
- * immediately followed by g so optimize the search for
- * this. We'll still do a full search just in case. */
- for (j = i + 1; j < ic->ic_nchans; j++) {
- c = &ic->ic_channels[j];
- if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
- return c;
- }
- for (j = 0; j < i; j++) {
- c = &ic->ic_channels[j];
- if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
- return c;
- }
- return NULL;
-}
-
/*
* Start an ap scan by populating the channel list.
*/
@@ -358,90 +206,15 @@ ap_start(struct ieee80211_scan_state *ss
{
struct ap_state *as = ss->ss_priv;
struct ieee80211com *ic = NULL;
- const struct scanlist *sl = NULL;
- struct ieee80211_channel *c = NULL;
int i;
unsigned int mode = 0;
SCAN_AP_LOCK_IRQ(as);
ic = vap->iv_ic;
/* Determine mode flags to match, or leave zero for auto mode */
- as->as_vap_desired_mode = vap->iv_des_mode;
- as->as_required_mode = 0;
- if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) {
- as->as_required_mode = chanflags[as->as_vap_desired_mode];
- if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) &&
- (as->as_required_mode != IEEE80211_CHAN_ST)) {
- /* Fixup for dynamic turbo flags */
- if (as->as_vap_desired_mode == IEEE80211_MODE_11G)
- as->as_required_mode = IEEE80211_CHAN_108G;
- else
- as->as_required_mode = IEEE80211_CHAN_108A;
- }
- }
-
ss->ss_last = 0;
- /* Use the table of ordered channels to construct the list
- * of channels for scanning. Any channels in the ordered
- * list not in the master list will be discarded. */
- for (sl = staScanTable; sl->list != NULL; sl++) {
- mode = sl->mode;
-
- /* The scan table marks 2.4Ghz channels as b
- * so if the desired mode is 11g, then use
- * the 11b channel list but upgrade the mode. */
- if (as->as_vap_desired_mode &&
- (as->as_vap_desired_mode != mode) &&
- (as->as_vap_desired_mode == IEEE80211_MODE_11G) &&
- (mode == IEEE80211_MODE_11B))
- mode = IEEE80211_MODE_11G;
-
- /* If we are in "AUTO" mode, upgrade the mode to auto.
- * This lets add_channels upgrade an 11b channel to
- * 11g if available. */
- if (!as->as_vap_desired_mode && (mode == IEEE80211_MODE_11B))
- mode = IEEE80211_MODE_AUTO;
-
- /* Add the list of the channels; any that are not
- * in the master channel list will be discarded. */
- add_channels(ic, ss, mode, sl->list, sl->count);
- }
-
- /* Add the channels from the ic (from HAL) that are not present
- * in the staScanTable, assuming they pass the sanity checks... */
- for (i = 0; i < ic->ic_nchans; i++) {
- c = &ic->ic_channels[i];
-
- /* XR is not supported on turbo channels */
- if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR)
- continue;
-
- /* Dynamic channels are scanned in base mode */
- if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c))
- continue;
-
- /* Use any 11g channel instead of 11b one. */
- if (vap->iv_des_mode == IEEE80211_MODE_AUTO &&
- IEEE80211_IS_CHAN_B(c) &&
- find11gchannel(ic, i, c->ic_freq))
- continue;
-
- /* Do not add channels already put into the scan list by the
- * scan table - these have already been filtered by mode
- * and for whether they are in the active channel list. */
- if (checktable(staScanTable, c))
- continue;
-
- /* Make sure the channel is active */
- if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
- continue;
+ ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
- /* Don't overrun */
- if (ss->ss_last >= IEEE80211_SCAN_MAX)
- break;
-
- ss->ss_chans[ss->ss_last++] = c;
- }
ss->ss_next = 0;
/* XXX tunables */
ss->ss_mindwell = msecs_to_jiffies(200); /* 200ms */
@@ -761,18 +534,6 @@ pick_channel(struct ieee80211_scan_state
if (IEEE80211_IS_CHAN_RADAR(c->chan))
continue;
- /* Do not select 802.11a ST if mode is specified and is not
- * 802.11a ST */
- if (as->as_required_mode &&
- IEEE80211_IS_CHAN_STURBO(c->chan) &&
- (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A))
- continue;
-
- /* Verify mode matches any fixed mode specified */
- if((c->chan->ic_flags & as->as_required_mode) !=
- as->as_required_mode)
- continue;
-
if ((ic->ic_bsschan != NULL) &&
(ic->ic_bsschan != IEEE80211_CHAN_ANYC)) {
--- a/net80211/ieee80211_scan.c
+++ b/net80211/ieee80211_scan.c
@@ -958,6 +958,80 @@ ieee80211_scan_flush(struct ieee80211com
}
}
+static const u_int chanflags[] = {
+ 0, /* IEEE80211_MODE_AUTO */
+ IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
+ IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
+ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
+ IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
+ IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
+ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */
+ IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */
+};
+
+static struct ieee80211_channel *
+find11gchannel(struct ieee80211com *ic, int i, int freq)
+{
+ struct ieee80211_channel *c;
+ int j;
+
+ /*
+ * The normal ordering in the channel list is b channel
+ * immediately followed by g so optimize the search for
+ * this. We'll still do a full search just in case.
+ */
+ for (j = i+1; j < ic->ic_nchans; j++) {
+ c = &ic->ic_channels[j];
+ if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+ return c;
+ }
+ for (j = 0; j < i; j++) {
+ c = &ic->ic_channels[j];
+ if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+ return c;
+ }
+ return NULL;
+}
+
+
+void
+ieee80211_scan_add_channels(struct ieee80211com *ic,
+ struct ieee80211_scan_state *ss,
+ enum ieee80211_phymode mode)
+{
+ struct ieee80211_channel *c, *cg;
+ u_int modeflags;
+ int i;
+
+ KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+ modeflags = chanflags[mode];
+ for (i = 0; i < ic->ic_nchans; i++) {
+ c = &ic->ic_channels[i];
+ if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
+ continue;
+ if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
+ continue;
+ if (modeflags &&
+ ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
+ (modeflags & IEEE80211_CHAN_ALLTURBO)))
+ continue;
+ if (mode == IEEE80211_MODE_AUTO) {
+ /*
+ * XXX special-case 11b/g channels so we select
+ * the g channel if both are present.
+ */
+ if (IEEE80211_IS_CHAN_B(c) &&
+ (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
+ continue;
+ }
+ if (ss->ss_last >= IEEE80211_SCAN_MAX)
+ break;
+ ss->ss_chans[ss->ss_last++] = c;
+ }
+}
+EXPORT_SYMBOL(ieee80211_scan_add_channels);
+
+
/*
* Execute radar channel change. This is called when a radar/dfs
* signal is detected. AP mode only. Return 1 on success, 0 on
--- a/net80211/ieee80211_scan.h
+++ b/net80211/ieee80211_scan.h
@@ -219,4 +219,7 @@ void ieee80211_scanner_register(enum iee
void ieee80211_scanner_unregister(enum ieee80211_opmode,
const struct ieee80211_scanner *);
void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
+void ieee80211_scan_add_channels(struct ieee80211com *ic,
+ struct ieee80211_scan_state *ss,
+ enum ieee80211_phymode mode);
#endif /* _NET80211_IEEE80211_SCAN_H_ */
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -3873,6 +3873,106 @@ ieee80211_ioctl_kickmac(struct net_devic
return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
}
+static inline void setflag(struct ieee80211_channel *c, int flag)
+{
+ if (flag)
+ c->ic_scanflags |= IEEE80211_NOSCAN_SET;
+ else
+ c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
+}
+
+static void setscanflag(struct ieee80211com *ic, int min, int max, int set)
+{
+ int i;
+
+ for (i = 0; i < ic->ic_nchans; i++) {
+ struct ieee80211_channel *c = &ic->ic_channels[i];
+
+ if (min == -1) {
+ if (!(c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT))
+ setflag(c, set);
+ } else if ((c->ic_freq >= min) && (c->ic_freq <= max)) {
+ setflag(c, set);
+ }
+ }
+}
+
+static int
+ieee80211_ioctl_setscanlist(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct ieee80211vap *vap = dev->priv;
+ struct ieee80211com *ic = vap->iv_ic;
+ char *s, *next;
+ int val = 1;
+
+ if (data->length <= 0)
+ return -EINVAL;
+
+ s = kmalloc(data->length + 1, GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ memset(s, 0, data->length + 1);
+ if (copy_from_user(s, data->pointer, data->length))
+ return -EFAULT;
+
+ s[data->length - 1] = '\0'; /* ensure null termination */
+
+ switch(*s) {
+ case '-':
+ val = 1;
+ break;
+ case '+':
+ val = 0;
+ break;
+ default:
+ goto error;
+ }
+ s++;
+ next = s;
+ do {
+ next = strchr(s, ',');
+ if (next) {
+ *next = 0;
+ next++;
+ }
+ if (!strcmp(s, "ALL")) {
+ setscanflag(ic, 0, 10000, val);
+ } else if (!strcmp(s, "REG")) {
+ setscanflag(ic, -1, -1, val);
+ } else {
+ int min, max;
+ char *n, *end = NULL;
+
+ n = strchr(s, '-');
+ if (n) {
+ *n = 0;
+ n++;
+ }
+ min = simple_strtoul(s, &end, 10);
+ if (end && *end)
+ goto error;
+ if (n) {
+ max = simple_strtoul(n, &end, 10);
+ if (end && *end)
+ goto error;
+ } else {
+ max = min;
+ }
+ setscanflag(ic, min, max, val);
+ }
+ s = next;
+ } while (next);
+ return 0;
+
+error:
+ if (s)
+ kfree(s);
+ return -EINVAL;
+}
+
static int
ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
@@ -5656,6 +5756,8 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
{IEEE80211_PARAM_MINRATE,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
+ { IEEE80211_IOCTL_SETSCANLIST,
+ IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
#ifdef ATH_REVERSE_ENGINEERING
/*
@@ -5753,6 +5855,7 @@ static const iw_handler ieee80211_priv_h
set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac),
set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac),
+ set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist),
#ifdef ATH_REVERSE_ENGINEERING
set_priv(IEEE80211_IOCTL_READREG, ieee80211_ioctl_readreg),
set_priv(IEEE80211_IOCTL_WRITEREG, ieee80211_ioctl_writereg),

View File

@ -0,0 +1,265 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1014,9 +1014,7 @@ ath_attach(u_int16_t devid, struct net_d
*/
sc->sc_hasveol = ath_hal_hasveol(ah);
- /* Interference mitigation/ambient noise immunity (ANI).
- * In modes other than HAL_M_STA, it causes receive sensitivity
- * problems for OFDM. */
+ /* Interference mitigation/ambient noise immunity (ANI). */
sc->sc_hasintmit = ath_hal_hasintmit(ah);
/* get mac address from hardware */
@@ -1144,6 +1142,11 @@ ath_attach(u_int16_t devid, struct net_d
sc->sc_rp_lasttsf = 0;
sc->sc_last_tsf = 0;
+ /* set all 3 to auto */
+ sc->sc_intmit = -1;
+ sc->sc_noise_immunity = -1;
+ sc->sc_ofdm_weak_det = -1;
+
return 0;
bad3:
ieee80211_ifdetach(ic);
@@ -2428,6 +2431,43 @@ ath_chan2flags(struct ieee80211_channel
return flags;
}
+static int ath_setintmit(struct ath_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int ret;
+ int val;
+
+ if (!sc->sc_hasintmit)
+ return 0;
+
+ switch(sc->sc_intmit) {
+ case -1:
+ if (sc->sc_opmode != IEEE80211_M_MONITOR)
+ val = 1;
+ else
+ val = 0;
+ break;
+ case 0: /* disabled */
+ case 1: /* enabled */
+ val = sc->sc_intmit;
+ break;
+ default:
+ return 0;
+ }
+ ret = ath_hal_setintmit(ah, val);
+ if (val)
+ goto done;
+
+ /* manual settings */
+ if ((sc->sc_noise_immunity >= 0) && (sc->sc_noise_immunity <= 5))
+ ath_hal_setcapability(ah, HAL_CAP_INTMIT, 2, sc->sc_noise_immunity, NULL);
+ if ((sc->sc_ofdm_weak_det == 0) || (sc->sc_ofdm_weak_det == 1))
+ ath_hal_setcapability(ah, HAL_CAP_INTMIT, 3, sc->sc_ofdm_weak_det, NULL);
+
+done:
+ return ret;
+}
+
/*
* Context: process context
*/
@@ -2493,8 +2533,7 @@ ath_init(struct net_device *dev)
if (sc->sc_softled)
ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
- if ((sc->sc_opmode != HAL_M_STA) && sc->sc_hasintmit)
- ath_hal_setintmit(ah, 0);
+ ath_setintmit(sc);
/*
* This is needed only to setup initial state
@@ -2530,7 +2569,7 @@ ath_init(struct net_device *dev)
* Enable MIB interrupts when there are hardware phy counters.
* Note we only do this (at the moment) for station mode.
*/
- if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)
+ if (sc->sc_needmib && ath_hal_getintmit(ah, NULL))
sc->sc_imask |= HAL_INT_MIB;
ath_hal_intrset(ah, sc->sc_imask);
@@ -2787,9 +2826,7 @@ ath_reset(struct net_device *dev)
EPRINTF(sc, "Unable to reset hardware: '%s' (HAL status %u)\n",
ath_get_hal_status_desc(status), status);
- if ((sc->sc_opmode != HAL_M_STA) && sc->sc_hasintmit)
- ath_hal_setintmit(ah, 0);
-
+ ath_setintmit(sc);
ath_update_txpow(sc); /* update tx power state */
ath_radar_update(sc);
ath_setdefantenna(sc, sc->sc_defant);
@@ -4174,6 +4211,8 @@ ath_calcrxfilter(struct ath_softc *sc)
if (sc->sc_nmonvaps > 0)
rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
HAL_RX_FILTER_PROBEREQ | HAL_RX_FILTER_PROM);
+ if (sc->sc_hasintmit && !sc->sc_needmib && ath_hal_getintmit(ah, NULL))
+ rfilt |= HAL_RX_FILTER_PHYERR;
if (sc->sc_curchan.privFlags & CHANNEL_DFS)
rfilt |= (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR);
return rfilt;
@@ -6526,9 +6565,6 @@ process_rx_again:
rs->rs_rssi = 0;
len = rs->rs_datalen;
- /* DMA sync. dies spectacularly if len == 0 */
- if (len == 0)
- goto rx_next;
if (rs->rs_more) {
/*
@@ -8876,9 +8912,7 @@ ath_chan_set(struct ath_softc *sc, struc
if (sc->sc_softled)
ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
- if ((sc->sc_opmode != HAL_M_STA) && sc->sc_hasintmit)
- ath_hal_setintmit(ah, 0);
-
+ ath_setintmit(sc);
sc->sc_curchan = hchan;
ath_update_txpow(sc); /* update tx power state */
ath_radar_update(sc);
@@ -10655,9 +10689,54 @@ enum {
ATH_RP_IGNORED = 24,
ATH_RADAR_IGNORED = 25,
ATH_MAXVAPS = 26,
+ ATH_INTMIT = 27,
+ ATH_NOISE_IMMUNITY = 28,
+ ATH_OFDM_WEAK_DET = 29
};
static int
+ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val)
+{
+ int ret;
+
+ switch(ctl) {
+ case ATH_INTMIT:
+ sc->sc_intmit = val;
+ break;
+ case ATH_NOISE_IMMUNITY:
+ sc->sc_noise_immunity = val;
+ break;
+ case ATH_OFDM_WEAK_DET:
+ sc->sc_ofdm_weak_det = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = ath_setintmit(sc);
+ ath_calcrxfilter(sc);
+ return ret;
+}
+
+static int
+ath_sysctl_get_intmit(struct ath_softc *sc, long ctl, u_int *val)
+{
+ struct ath_hal *ah = sc->sc_ah;
+
+ switch(ctl) {
+ case ATH_INTMIT:
+ *val = (ath_hal_getcapability(ah, HAL_CAP_INTMIT, 1, NULL) == HAL_OK);
+ break;
+ case ATH_NOISE_IMMUNITY:
+ return ath_hal_getcapability(ah, HAL_CAP_INTMIT, 2, val);
+ case ATH_OFDM_WEAK_DET:
+ return ath_hal_getcapability(ah, HAL_CAP_INTMIT, 3, val);
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int
ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
{
struct ath_softc *sc = ctl->extra1;
@@ -10843,6 +10922,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
case ATH_RADAR_IGNORED:
sc->sc_radar_ignored = val;
break;
+ case ATH_INTMIT:
+ case ATH_NOISE_IMMUNITY:
+ case ATH_OFDM_WEAK_DET:
+ ret = ath_sysctl_set_intmit(sc, (long)ctl->extra2, val);
+ break;
default:
ret = -EINVAL;
break;
@@ -10909,6 +10993,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
case ATH_RADAR_IGNORED:
val = sc->sc_radar_ignored;
break;
+ case ATH_INTMIT:
+ case ATH_NOISE_IMMUNITY:
+ case ATH_OFDM_WEAK_DET:
+ ret = ath_sysctl_get_intmit(sc, (long)ctl->extra2, &val);
+ break;
default:
ret = -EINVAL;
break;
@@ -11086,6 +11175,24 @@ static const ctl_table ath_sysctl_templa
.proc_handler = ath_sysctl_halparam,
.extra2 = (void *)ATH_RADAR_IGNORED,
},
+ { .ctl_name = CTL_AUTO,
+ .procname = "intmit",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_INTMIT,
+ },
+ { .ctl_name = CTL_AUTO,
+ .procname = "noise_immunity",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_NOISE_IMMUNITY,
+ },
+ { .ctl_name = CTL_AUTO,
+ .procname = "ofdm_weak_det",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_OFDM_WEAK_DET,
+ },
{ 0 }
};
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -693,6 +693,10 @@ struct ath_softc {
unsigned int sc_txcont_power; /* Continuous transmit power in 0.5dBm units */
unsigned int sc_txcont_rate; /* Continuous transmit rate in Mbps */
+ int8_t sc_intmit; /* Interference mitigation enabled, -1 = auto, based on mode, 0/1 = off/on */
+ int8_t sc_noise_immunity; /* Noise immunity level, 0-4, -1 == auto) */
+ int8_t sc_ofdm_weak_det; /* OFDM weak frames detection, -1 == auto */
+
/* rate tables */
const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX];
const HAL_RATE_TABLE *sc_currates; /* current rate table */
--- a/ath/if_ath_hal.h
+++ b/ath/if_ath_hal.h
@@ -67,14 +67,14 @@ static inline HAL_POWER_MODE ath_hal_get
static inline HAL_BOOL ath_hal_getdiagstate(struct ath_hal *ah, int request,
const void *args, u_int32_t argsize,
- void **result,
+ void *result,
u_int32_t *resultsize)
{
HAL_BOOL ret;
ATH_HAL_LOCK_IRQ(ah->ah_sc);
ath_hal_set_function(__func__);
ret =
- ah->ah_getDiagState(ah, request, args, argsize, *result,
+ ah->ah_getDiagState(ah, request, args, argsize, result,
resultsize);
ath_hal_set_function(NULL);
ATH_HAL_UNLOCK_IRQ(ah->ah_sc);

View File

@ -0,0 +1,19 @@
--- a/ath/if_ath_pci.c
+++ b/ath/if_ath_pci.c
@@ -114,11 +114,15 @@ static struct pci_device_id ath_pci_id_t
{ 0x168c, 0x0023, PCI_ANY_ID, PCI_ANY_ID },
{ 0x168c, 0x0024, PCI_ANY_ID, PCI_ANY_ID },
{ 0x168c, 0x9013, PCI_ANY_ID, PCI_ANY_ID }, /* sonicwall */
+ { 0x168c, 0xff16, PCI_ANY_ID, PCI_ANY_ID },
+ { 0x168c, 0xff1a, PCI_ANY_ID, PCI_ANY_ID },
{ 0 }
};
static u16 ath_devidmap[][2] = {
- { 0x9013, 0x0013 }
+ { 0x9013, 0x0013 },
+ { 0xff16, 0x0013 },
+ { 0xff1a, 0x001a }
};
static int

View File

@ -0,0 +1,95 @@
--- a/ath_hal/ah_os.c
+++ b/ath_hal/ah_os.c
@@ -343,6 +343,46 @@ EXPORT_SYMBOL(ath_hal_func);
* NB: see the comments in ah_osdep.h about byte-swapping register
* reads and writes to understand what's going on below.
*/
+
+#ifdef CONFIG_LANTIQ
+extern int lantiq_emulate_madwifi_eep;
+extern unsigned long long lantiq_madwifi_eep_addr;
+#define EEPROM_EMULATION 1
+#endif
+
+#ifdef EEPROM_EMULATION
+static int ath_hal_eeprom(struct ath_hal *ah, unsigned long addr, int val, int write)
+{
+ static int addrsel = 0;
+ static int rc = 0;
+
+ if (write) {
+ if(addr == 0x6000) {
+ addrsel = val * 2;
+ rc = 0;
+ }
+ } else {
+ switch(addr)
+ {
+ case 0x600c:
+ if(rc++ < 2)
+ val = 0x00000000;
+ else
+ val = 0x00000002;
+ break;
+ case 0x6004:
+ val = cpu_to_le16(__raw_readw((u16 *) KSEG1ADDR(lantiq_madwifi_eep_addr + addrsel)));
+ /* this forces the regdomain to 0x00 (worldwide), as the original setting
+ * causes issues with the HAL */
+ if (addrsel == 0x17e)
+ val = 0;
+ break;
+ }
+ }
+ return val;
+}
+#endif
+
void __ahdecl
ath_hal_reg_write(struct ath_hal *ah, u_int reg, u_int32_t val)
{
@@ -351,20 +391,33 @@ ath_hal_reg_write(struct ath_hal *ah, u_
ath_hal_printf(ah, "%s: WRITE 0x%x <= 0x%x\n",
(ath_hal_func ?: "unknown"), reg, val);
#endif
- _OS_REG_WRITE(ah, reg, val);
+#ifdef EEPROM_EMULATION
+ if((reg >= 0x6000) && (reg <= 0x6010) && lantiq_emulate_madwifi_eep)
+ {
+ val = ath_hal_eeprom(ah, reg, val, 1);
+ } else
+#endif
+ _OS_REG_WRITE(ah, reg, val);
}
EXPORT_SYMBOL(ath_hal_reg_write);
+
/* This should only be called while holding the lock, sc->sc_hal_lock. */
u_int32_t __ahdecl
ath_hal_reg_read(struct ath_hal *ah, u_int reg)
{
- u_int32_t val;
+ u_int32_t val;
+#ifdef EEPROM_EMULATION
+ if((reg >= 0x6000) && (reg <= 0x6010) && lantiq_emulate_madwifi_eep)
+ {
+ val = ath_hal_eeprom(ah, reg, 0, 0);
+ } else
+#endif
+ val = _OS_REG_READ(ah, reg);
- val = _OS_REG_READ(ah, reg);
#ifdef AH_DEBUG
if (ath_hal_debug > 1)
- ath_hal_printf(ah, "%s: READ 0x%x => 0x%x\n",
+ ath_hal_printf(ah, "%s: READ 0x%x => 0x%x\n",
(ath_hal_func ?: "unknown"), reg, val);
#endif
return val;
@@ -581,7 +634,6 @@ init_ath_hal(void)
{
const char *sep;
int i;
-
printk(KERN_INFO "%s: %s (", dev_info, ath_hal_version);
sep = "";
for (i = 0; ath_hal_buildopts[i] != NULL; i++) {

View File

@ -0,0 +1,77 @@
This patch causes STA mode interfaces to disassociate if transmission of assoc/auth
critical packets failed.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -8334,6 +8334,14 @@ ath_tx_processq(struct ath_softc *sc, st
#endif
if (ts->ts_status & HAL_TXERR_XRETRY) {
sc->sc_stats.ast_tx_xretries++;
+ if (SKB_CB(bf->bf_skb)->auth_pkt &&
+ (ni->ni_vap->iv_opmode == IEEE80211_M_STA)) {
+ struct ieee80211vap *vap = ni->ni_vap;
+
+ /* if roaming is enabled, try reassociating, otherwise
+ * disassociate and go back to the scan state */
+ vap->iv_mgtsend.function(vap->iv_mgtsend.data);
+ }
if (ni->ni_flags & IEEE80211_NODE_UAPSD_TRIG) {
ni->ni_stats.ns_tx_eosplost++;
DPRINTF(sc, ATH_DEBUG_UAPSD,
--- a/net80211/ieee80211_linux.c
+++ b/net80211/ieee80211_linux.c
@@ -156,6 +156,7 @@ ieee80211_getmgtframe(u_int8_t **frm, u_
if (off != 0)
skb_reserve(skb, align - off);
+ SKB_CB(skb)->auth_pkt = 0;
SKB_CB(skb)->ni = NULL;
SKB_CB(skb)->flags = 0;
SKB_CB(skb)->next = NULL;
--- a/net80211/ieee80211_linux.h
+++ b/net80211/ieee80211_linux.h
@@ -393,6 +393,7 @@ typedef spinlock_t acl_lock_t;
void (*next_destructor)(struct sk_buff *skb);
#endif
struct sk_buff *next; /* fast frame sk_buf chain */
+ u_int8_t auth_pkt;
};
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -778,6 +778,8 @@ ieee80211_encap(struct ieee80211_node *n
else
hdrsize = sizeof(struct ieee80211_frame);
+ SKB_CB(skb)->auth_pkt = (eh.ether_type == __constant_htons(ETHERTYPE_PAE));
+
switch (vap->iv_opmode) {
case IEEE80211_M_IBSS:
case IEEE80211_M_AHDEMO:
@@ -1622,6 +1624,7 @@ ieee80211_add_xr_param(u_int8_t *frm, st
ie->param_len = frm - &ie->param_oui[0];
return frm;
}
+
#endif
/*
* Send a probe request frame with the specified ssid
@@ -1886,6 +1889,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0));
if (skb == NULL)
senderr(ENOMEM, is_tx_nobuf);
+ SKB_CB(skb)->auth_pkt = 1;
((__le16 *)frm)[0] =
(is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED)
@@ -1960,6 +1964,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length);
if (skb == NULL)
senderr(ENOMEM, is_tx_nobuf);
+ SKB_CB(skb)->auth_pkt = 1;
capinfo = 0;
if (vap->iv_opmode == IEEE80211_M_IBSS)

View File

@ -0,0 +1,49 @@
This patch fixes the detection of hidden SSIDs as transmitted
by some cisco systems.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_scan_sta.c
+++ b/net80211/ieee80211_scan_sta.c
@@ -209,6 +209,19 @@ saveie(u_int8_t **iep, const u_int8_t *i
ieee80211_saveie(iep, ie);
}
+
+static inline int is_empty_ssid(u_int8_t *ssid)
+{
+ if (!ssid)
+ return 1;
+ if (ssid[1] == 0)
+ return 1;
+ if ((ssid[1] == 1) && (ssid[2] == 0))
+ return 1;
+ return 0;
+}
+
+
/*
* Process a beacon or probe response frame; create an
* entry in the scan cache or update any previous entry.
@@ -233,8 +246,8 @@ sta_add(struct ieee80211_scan_state *ss,
SCAN_STA_LOCK_IRQ(st);
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) &&
- sp->ssid[1] == se->base.se_ssid[1] &&
- !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1]))
+ (is_empty_ssid(sp->ssid) || (sp->ssid[1] == se->base.se_ssid[1] &&
+ !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1]))))
goto found;
MALLOC(se, struct sta_entry *, sizeof(struct sta_entry),
@@ -252,8 +265,8 @@ found:
ise = &se->base;
/* XXX ap beaconing multiple ssid w/ same bssid */
- if (sp->ssid[1] != 0 &&
- (ISPROBE(subtype) || ise->se_ssid[1] == 0))
+ if (!is_empty_ssid(sp->ssid) &&
+ (ISPROBE(subtype) || is_empty_ssid(ise->se_ssid)))
memcpy(ise->se_ssid, sp->ssid, 2 + sp->ssid[1]);
memcpy(ise->se_rates, sp->rates,

View File

@ -0,0 +1,160 @@
Add an optional background scanning threshold triggered by low rssi
(useful for passing updated scan results to the supplicant ahead of
time, before losing connectivity entirely)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -646,6 +646,7 @@ enum {
IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */
IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
+ IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -92,6 +92,8 @@
#define IEEE80211_BGSCAN_IDLE_MIN 100 /* min idle time (ms) */
#define IEEE80211_BGSCAN_IDLE_DEFAULT 250 /* default idle time (ms) */
+#define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
+
#define IEEE80211_COVERAGE_CLASS_MAX 31 /* max coverage class */
#define IEEE80211_REGCLASSIDS_MAX 10 /* max regclass id list */
@@ -219,6 +221,10 @@ struct ieee80211vap {
u_int8_t iv_nickname[IEEE80211_NWID_LEN];
u_int iv_bgscanidle; /* bg scan idle threshold */
u_int iv_bgscanintvl; /* bg scan min interval */
+ u_int iv_bgscanthr; /* bg scan rssi threshold */
+ u_int iv_bgscantrintvl; /* bg scan trigger interval */
+ unsigned long iv_bgscanthr_next; /* last trigger for bgscan */
+ unsigned long iv_lastconnect; /* time of last connect attempt */
u_int iv_scanvalid; /* scan cache valid threshold */
struct ieee80211_roam iv_roam; /* sta-mode roaming state */
@@ -608,6 +614,7 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_FEXT_SWBMISS 0x00000400 /* CONF: use software beacon timer */
#define IEEE80211_FEXT_DROPUNENC_EAPOL 0x00000800 /* CONF: drop unencrypted eapol frames */
#define IEEE80211_FEXT_APPIE_UPDATE 0x00001000 /* STATE: beacon APP IE updated */
+#define IEEE80211_FEXT_BGSCAN_THR 0x00002000 /* bgscan due to low rssi */
#define IEEE80211_COM_UAPSD_ENABLE(_ic) ((_ic)->ic_flags_ext |= IEEE80211_FEXT_UAPSD)
#define IEEE80211_COM_UAPSD_DISABLE(_ic) ((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_UAPSD)
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2744,6 +2744,9 @@ ieee80211_ioctl_setparam(struct net_devi
else
retv = EINVAL;
break;
+ case IEEE80211_PARAM_BGSCAN_THRESH:
+ vap->iv_bgscanthr = value;
+ break;
case IEEE80211_PARAM_MCAST_RATE:
/* units are in KILObits per second */
if (value >= 256 && value <= 54000)
@@ -3144,6 +3147,9 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_BGSCAN_INTERVAL:
param[0] = vap->iv_bgscanintvl / HZ; /* seconds */
break;
+ case IEEE80211_PARAM_BGSCAN_THRESH:
+ param[0] = vap->iv_bgscanthr; /* rssi */
+ break;
case IEEE80211_PARAM_MCAST_RATE:
param[0] = vap->iv_mcast_rate; /* seconds */
break;
@@ -5666,6 +5672,10 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanintvl" },
{ IEEE80211_PARAM_BGSCAN_INTERVAL,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanintvl" },
+ { IEEE80211_PARAM_BGSCAN_THRESH,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanthr" },
+ { IEEE80211_PARAM_BGSCAN_THRESH,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanthr" },
{ IEEE80211_PARAM_MCAST_RATE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcast_rate" },
{ IEEE80211_PARAM_MCAST_RATE,
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3013,8 +3013,10 @@ contbgscan(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
+ vap->iv_bgscantrintvl = (vap->iv_bgscantrintvl + 1) % 4;
return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
- time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle));
+ (((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && !vap->iv_bgscantrintvl) ||
+ time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle)));
}
static __inline int
@@ -3258,6 +3260,25 @@ ieee80211_recv_mgmt(struct ieee80211vap
/* record tsf of last beacon */
memcpy(ni->ni_tstamp.data, scan.tstamp,
sizeof(ni->ni_tstamp));
+
+ /* When rssi is low, start doing bgscans more frequently to allow
+ * the supplicant to make a better switching decision */
+ if (!(ic->ic_flags & IEEE80211_F_SCAN) && (rssi < vap->iv_bgscanthr) &&
+ (!vap->iv_bgscanthr_next ||
+ !time_before(jiffies, vap->iv_bgscanthr_next)) &&
+ (vap->iv_state == IEEE80211_S_RUN) &&
+ time_after(jiffies, vap->iv_lastconnect +
+ msecs_to_jiffies(IEEE80211_BGSCAN_INTVAL_MIN * 1000))) {
+ int ret;
+
+ ic->ic_lastdata = 0;
+ ic->ic_lastscan = 0;
+ ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN_THR;
+ ret = ieee80211_bg_scan(vap);
+ if (ret)
+ vap->iv_bgscanthr_next = jiffies + msecs_to_jiffies(IEEE80211_BGSCAN_TRIGGER_INTVL * 1000);
+ }
+
if (ni->ni_intval != scan.bintval) {
IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
"beacon interval divergence: "
--- a/net80211/ieee80211_scan.c
+++ b/net80211/ieee80211_scan.c
@@ -616,6 +616,7 @@ ieee80211_cancel_scan(struct ieee80211va
/* clear bg scan NOPICK and mark cancel request */
ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
+ ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN_THR;
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
ss->ss_ops->scan_cancel(ss, vap);
/* force it to fire asap */
@@ -782,7 +783,7 @@ again:
ieee80211_sta_pwrsave(vap, 0);
if (ss->ss_next >= ss->ss_last) {
ieee80211_notify_scan_done(vap);
- ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
+ ic->ic_flags_ext &= ~(IEEE80211_FEXT_BGSCAN|IEEE80211_FEXT_BGSCAN_THR);
}
}
SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;
--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
@@ -1450,6 +1450,7 @@ __ieee80211_newstate(struct ieee80211vap
}
break;
case IEEE80211_S_AUTH:
+ vap->iv_lastconnect = jiffies;
/* auth frames are possible between IBSS nodes,
* see 802.11-1999, chapter 5.7.6 */
KASSERT(vap->iv_opmode == IEEE80211_M_STA ||
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -238,7 +238,8 @@ ieee80211_hardstart(struct sk_buff *skb,
}
/* Cancel any running BG scan */
- ieee80211_cancel_scan(vap);
+ if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && (vap->iv_state == IEEE80211_S_RUN))
+ ieee80211_cancel_scan(vap);
/*
* Find the node for the destination so we can do

View File

@ -0,0 +1,18 @@
Some misconfigured APs broadcast NULL BSSIDs, which can confuse the STA
Ignore those when scanning.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_scan_sta.c
+++ b/net80211/ieee80211_scan_sta.c
@@ -242,6 +242,10 @@ sta_add(struct ieee80211_scan_state *ss,
struct ieee80211_scan_entry *ise;
int hash;
+ /* workaround for broken APs that broadcast NULL BSSIDs */
+ if (memcmp(wh->i_addr3, "\x00\x00\x00\x00\x00\x00", 6) == 0)
+ return 0;
+
hash = STA_HASH(macaddr);
SCAN_STA_LOCK_IRQ(st);
LIST_FOREACH(se, &st->st_hash[hash], se_hash)

View File

@ -0,0 +1,31 @@
Add a preliminary fix for the reassoc check, but disable reassoc entirely for now
until we've figured out why it fails frequently.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -599,10 +599,9 @@ ieee80211_ibss_merge(struct ieee80211_no
EXPORT_SYMBOL(ieee80211_ibss_merge);
static __inline int
-ssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b)
+bssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b)
{
- return (a->ni_esslen == b->ni_esslen &&
- memcmp(a->ni_essid, b->ni_essid, a->ni_esslen) == 0);
+ return (memcmp(a->ni_bssid, b->ni_bssid, IEEE80211_ADDR_LEN) == 0);
}
/*
@@ -634,8 +633,8 @@ ieee80211_sta_join1(struct ieee80211_nod
* Check if old+new node have the same ssid in which
* case we can reassociate when operating in sta mode.
*/
- canreassoc = ((obss != NULL) &&
- (vap->iv_state == IEEE80211_S_RUN) && ssid_equal(obss, selbs));
+ canreassoc = 0; /* ((obss != NULL) &&
+ (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
vap->iv_bss = selbs;
IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
if (obss != NULL)

View File

@ -0,0 +1,242 @@
Drop stale AP nodes from the client list when disconnecting.
Fixes some reassoc issues.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
@@ -1348,7 +1348,7 @@ __ieee80211_newstate(struct ieee80211vap
IEEE80211_SEND_MGMT(ni,
IEEE80211_FC0_SUBTYPE_DISASSOC,
IEEE80211_REASON_ASSOC_LEAVE);
- ieee80211_sta_leave(ni);
+ ieee80211_node_leave(ni);
break;
case IEEE80211_M_HOSTAP:
ieee80211_iterate_nodes(&ic->ic_sta,
@@ -1358,12 +1358,14 @@ __ieee80211_newstate(struct ieee80211vap
break;
}
goto reset;
+ case IEEE80211_S_AUTH:
case IEEE80211_S_ASSOC:
switch (vap->iv_opmode) {
case IEEE80211_M_STA:
IEEE80211_SEND_MGMT(ni,
IEEE80211_FC0_SUBTYPE_DEAUTH,
IEEE80211_REASON_AUTH_LEAVE);
+ ieee80211_node_leave(ni);
break;
case IEEE80211_M_HOSTAP:
ieee80211_iterate_nodes(&ic->ic_sta,
@@ -1376,7 +1378,6 @@ __ieee80211_newstate(struct ieee80211vap
case IEEE80211_S_SCAN:
ieee80211_cancel_scan(vap);
goto reset;
- case IEEE80211_S_AUTH:
reset:
ieee80211_reset_bss(vap);
break;
@@ -1429,10 +1430,12 @@ __ieee80211_newstate(struct ieee80211vap
IEEE80211_SCAN_FOREVER,
vap->iv_des_nssid, vap->iv_des_ssid,
NULL);
+ else
+ ieee80211_node_leave(vap->iv_bss);
break;
case IEEE80211_S_RUN: /* beacon miss */
if (vap->iv_opmode == IEEE80211_M_STA) {
- ieee80211_sta_leave(ni);
+ ieee80211_node_leave(ni);
vap->iv_flags &= ~IEEE80211_F_SIBSS; /* XXX */
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
ieee80211_check_scan(vap,
@@ -1511,7 +1514,7 @@ __ieee80211_newstate(struct ieee80211vap
IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
break;
case IEEE80211_S_RUN:
- ieee80211_sta_leave(ni);
+ ieee80211_node_leave(ni);
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
/* NB: caller specifies ASSOC/REASSOC by arg */
IEEE80211_SEND_MGMT(ni, arg ?
@@ -1779,6 +1782,7 @@ ieee80211_newstate(struct ieee80211vap *
ieee80211_state_name[nstate],
ieee80211_state_name[dstate]);
+ ieee80211_update_link_status(vap, nstate, ostate);
switch (nstate) {
case IEEE80211_S_AUTH:
case IEEE80211_S_ASSOC:
--- a/net80211/ieee80211_linux.c
+++ b/net80211/ieee80211_linux.c
@@ -233,33 +233,59 @@ ieee80211_vlan_vdetach(struct ieee80211v
}
void
-ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
+ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate)
{
- struct ieee80211vap *vap = ni->ni_vap;
struct net_device *dev = vap->iv_dev;
union iwreq_data wreq;
+ int active;
+
+ if (vap->iv_opmode != IEEE80211_M_STA)
+ return;
+
+ if (ostate == nstate)
+ return;
+
+ if (nstate == IEEE80211_S_RUN)
+ active = 1;
+ else if ((ostate >= IEEE80211_S_AUTH) && (nstate < ostate))
+ active = 0;
+ else
+ return;
+
+ if (active && !vap->iv_bss)
+ return;
+
+ memset(&wreq, 0, sizeof(wreq));
+ wreq.ap_addr.sa_family = ARPHRD_ETHER;
- if (ni == vap->iv_bss) {
- if (newassoc)
- netif_carrier_on(dev);
- memset(&wreq, 0, sizeof(wreq));
+ if (active) {
+ //netif_carrier_on(vap->iv_dev);
IEEE80211_ADDR_COPY(wreq.addr.sa_data, vap->iv_bssid);
- wreq.addr.sa_family = ARPHRD_ETHER;
-#ifdef ATH_SUPERG_XR
- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
- dev = vap->iv_xrvap->iv_dev;
-#endif
- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
} else {
- memset(&wreq, 0, sizeof(wreq));
- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
- wreq.addr.sa_family = ARPHRD_ETHER;
+ //netif_carrier_off(vap->iv_dev);
+ memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
+ }
+ wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
+}
+
+void
+ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct net_device *dev = vap->iv_dev;
+ union iwreq_data wreq;
+
+ if (ni == vap->iv_bss)
+ return;
+
+ memset(&wreq, 0, sizeof(wreq));
+ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
+ wreq.addr.sa_family = ARPHRD_ETHER;
#ifdef ATH_SUPERG_XR
- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
- dev = vap->iv_xrvap->iv_dev;
+ if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
+ dev = vap->iv_xrvap->iv_dev;
#endif
- wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
- }
+ wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
}
void
@@ -269,18 +295,14 @@ ieee80211_notify_node_leave(struct ieee8
struct net_device *dev = vap->iv_dev;
union iwreq_data wreq;
- if (ni == vap->iv_bss) {
- netif_carrier_off(dev);
- memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
- wreq.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
- } else {
- /* fire off wireless event station leaving */
- memset(&wreq, 0, sizeof(wreq));
- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
- wreq.addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
- }
+ if (ni == vap->iv_bss)
+ return;
+
+ /* fire off wireless event station leaving */
+ memset(&wreq, 0, sizeof(wreq));
+ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
+ wreq.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
}
void
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -2332,6 +2332,7 @@ ieee80211_node_leave(struct ieee80211_no
count_suppchans(ic, ni, -1);
IEEE80211_UNLOCK_IRQ(ic);
+done:
/*
* Cleanup station state. In particular clear various
* state that might otherwise be reused if the node
@@ -2339,7 +2340,7 @@ ieee80211_node_leave(struct ieee80211_no
* (and memory is reclaimed).
*/
ieee80211_sta_leave(ni);
-done:
+
/* Run a cleanup */
#ifdef IEEE80211_DEBUG_REFCNT
ic->ic_node_cleanup_debug(ni, __func__, __LINE__);
--- a/net80211/ieee80211_node.h
+++ b/net80211/ieee80211_node.h
@@ -60,7 +60,7 @@
#define IEEE80211_INACT_PROBE (30/IEEE80211_INACT_WAIT) /* probe */
#define IEEE80211_INACT_SCAN (300/IEEE80211_INACT_WAIT) /* scanned */
-#define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */
+#define IEEE80211_TRANS_WAIT 300 /* mgt frame tx timer (msecs) */
#define IEEE80211_NODE_HASHSIZE 32
/* simple hash is enough for variation of macaddr */
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -2141,7 +2141,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type);
if (timer)
- mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
+ mod_timer(&vap->iv_mgtsend, jiffies + msecs_to_jiffies(timer));
return 0;
bad:
return ret;
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -514,8 +514,9 @@ ieee80211_ioctl_siwap(struct net_device
vap->iv_flags |= IEEE80211_F_DESBSSID;
IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);
- if (IS_UP_AUTO(vap))
+ if (IS_UP(vap->iv_dev)) {
ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ }
}
return 0;
}
--- a/net80211/ieee80211_linux.h
+++ b/net80211/ieee80211_linux.h
@@ -643,6 +643,7 @@ void ieee80211_vlan_vdetach(struct ieee8
#define free_netdev(dev) kfree(dev)
#endif
+void ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate);
void ieee80211_ioctl_vattach(struct ieee80211vap *);
void ieee80211_ioctl_vdetach(struct ieee80211vap *);
struct ifreq;

View File

@ -0,0 +1,102 @@
Improve the beacon miss handling. Instead of just dropping the connection,
send a directed probe request to the AP to see if it's still responding.
Schedule a software beacon miss timer in this case, which adds a timeout
for the APs probe response.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3400,12 +3400,17 @@ ieee80211_recv_mgmt(struct ieee80211vap
}
/* WDS/Repeater: re-schedule software beacon timer for
- * STA. */
- if ((vap->iv_state == IEEE80211_S_RUN) &&
- (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
- mod_timer(&vap->iv_swbmiss,
+ * STA. Reset consecutive bmiss counter as well */
+ IEEE80211_LOCK_IRQ(ic);
+ if (vap->iv_state == IEEE80211_S_RUN) {
+ vap->iv_bmiss_count = 0;
+ if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)
+ mod_timer(&vap->iv_swbmiss,
jiffies + vap->iv_swbmiss_period);
+ else
+ del_timer(&vap->iv_swbmiss);
}
+ IEEE80211_UNLOCK_IRQ(ic);
/* If scanning, pass the info to the scan module.
* Otherwise, check if it's the right time to do
--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
@@ -1209,6 +1209,8 @@ ieee80211_beacon_miss(struct ieee80211co
}
/* XXX locking */
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ int count;
+
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
"%s\n", "beacon miss");
@@ -1221,6 +1223,29 @@ ieee80211_beacon_miss(struct ieee80211co
if (vap->iv_opmode != IEEE80211_M_STA ||
vap->iv_state != IEEE80211_S_RUN)
continue;
+
+ IEEE80211_LOCK_IRQ(ic);
+ count = vap->iv_bmiss_count++;
+ if (count) {
+ /* if the counter was already above zero, reset it
+ * here, since we're going to do the bmiss handling
+ * in any case */
+ vap->iv_bmiss_count = 0;
+ } else {
+ /* schedule the software beacon miss timer, it will be
+ * cancelled, if the probe request is acked */
+ mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
+ }
+ IEEE80211_UNLOCK_IRQ(ic);
+
+ if (!count) {
+ ieee80211_send_probereq(vap->iv_bss, vap->iv_myaddr,
+ vap->iv_bss->ni_bssid, vap->iv_bss->ni_bssid,
+ vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen,
+ NULL, 0);
+ continue;
+ }
+
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
#ifdef ATH_SUPERG_DYNTURBO
/*
@@ -1621,14 +1646,14 @@ __ieee80211_newstate(struct ieee80211vap
}
/* WDS/Repeater: Start software beacon timer for STA */
+ vap->iv_swbmiss.function = ieee80211_sta_swbmiss;
+ vap->iv_swbmiss.data = (unsigned long) vap;
+ vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(
+ vap->iv_ic->ic_bmissthreshold * ni->ni_intval);
+
if (ostate != IEEE80211_S_RUN &&
(vap->iv_opmode == IEEE80211_M_STA &&
vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
- vap->iv_swbmiss.function = ieee80211_sta_swbmiss;
- vap->iv_swbmiss.data = (unsigned long) vap;
- vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(
- vap->iv_ic->ic_bmissthreshold * ni->ni_intval);
-
mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
}
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -283,6 +283,7 @@ struct ieee80211vap {
struct timer_list iv_swbmiss; /* software beacon miss timer */
u_int16_t iv_swbmiss_period; /* software beacon miss timer period */
+ u_int16_t iv_bmiss_count; /* consecutive beacon miss counter */
struct ieee80211_nsparams iv_nsparams; /* new state parameters for tasklet for stajoin1 */
struct IEEE80211_TQ_STRUCT iv_stajoin1tq; /* tasklet for newstate action called from stajoin1tq */
unsigned int iv_nsdone; /* Done with scheduled newstate tasklet */

View File

@ -0,0 +1,93 @@
Add an optional threshold for low-rssi disconnection. This can be useful
when letting wpa_supplicant control roaming.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -647,6 +647,8 @@ enum {
IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
+ IEEE80211_PARAM_RSSI_DIS_THR = 80, /* rssi threshold for disconnection */
+ IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2799,6 +2799,12 @@ ieee80211_ioctl_setparam(struct net_devi
case IEEE80211_PARAM_ROAM_RATE_11G:
vap->iv_roam.rate11b = value;
break;
+ case IEEE80211_PARAM_RSSI_DIS_THR:
+ vap->iv_rssi_dis_thr = value;
+ break;
+ case IEEE80211_PARAM_RSSI_DIS_COUNT:
+ vap->iv_rssi_dis_max = value;
+ break;
case IEEE80211_PARAM_UAPSDINFO:
if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
if (ic->ic_caps & IEEE80211_C_UAPSD) {
@@ -3184,6 +3190,12 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_ROAM_RATE_11G:
param[0] = vap->iv_roam.rate11b;
break;
+ case IEEE80211_PARAM_RSSI_DIS_THR:
+ param[0] = vap->iv_rssi_dis_thr;
+ break;
+ case IEEE80211_PARAM_RSSI_DIS_COUNT:
+ param[0] = vap->iv_rssi_dis_max;
+ break;
case IEEE80211_PARAM_UAPSDINFO:
if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
if (IEEE80211_VAP_UAPSD_ENABLED(vap))
@@ -5733,6 +5745,14 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rate11g" },
{ IEEE80211_PARAM_ROAM_RATE_11G,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rate11g" },
+ { IEEE80211_PARAM_RSSI_DIS_THR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_disthr" },
+ { IEEE80211_PARAM_RSSI_DIS_THR,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_disthr" },
+ { IEEE80211_PARAM_RSSI_DIS_COUNT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_discnt" },
+ { IEEE80211_PARAM_RSSI_DIS_COUNT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_discnt" },
{ IEEE80211_PARAM_UAPSDINFO,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "uapsd" },
{ IEEE80211_PARAM_UAPSDINFO,
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3261,6 +3261,19 @@ ieee80211_recv_mgmt(struct ieee80211vap
memcpy(ni->ni_tstamp.data, scan.tstamp,
sizeof(ni->ni_tstamp));
+ /* when rssi falls below the disconnection threshold, drop the connection */
+ if ((vap->iv_rssi_dis_thr > 0) && (vap->iv_rssi_dis_max > 0)) {
+ if ((rssi > 0) && (rssi < vap->iv_rssi_dis_thr)) {
+ if (++vap->iv_rssi_dis_trig > vap->iv_rssi_dis_max) {
+ vap->iv_rssi_dis_trig = 0;
+ ieee80211_node_leave(ni);
+ return;
+ }
+ } else {
+ vap->iv_rssi_dis_trig = 0;
+ }
+ }
+
/* When rssi is low, start doing bgscans more frequently to allow
* the supplicant to make a better switching decision */
if (!(ic->ic_flags & IEEE80211_F_SCAN) && (rssi < vap->iv_bgscanthr) &&
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -223,6 +223,9 @@ struct ieee80211vap {
u_int iv_bgscanintvl; /* bg scan min interval */
u_int iv_bgscanthr; /* bg scan rssi threshold */
u_int iv_bgscantrintvl; /* bg scan trigger interval */
+ u_int iv_rssi_dis_thr; /* rssi disassoc threshold */
+ u_int iv_rssi_dis_max; /* max beacons below disconnect threshold */
+ u_int iv_rssi_dis_trig; /* rssi disassoc trigger count */
unsigned long iv_bgscanthr_next; /* last trigger for bgscan */
unsigned long iv_lastconnect; /* time of last connect attempt */
u_int iv_scanvalid; /* scan cache valid threshold */

View File

@ -0,0 +1,11 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -4925,7 +4925,7 @@ ath_beacon_generate(struct ath_softc *sc
* capability info and arrange for a mode change
* if needed.
*/
- if (sc->sc_dturbo) {
+ if (sc->sc_dturbo && NULL != avp->av_boff.bo_tim) {
u_int8_t dtim;
dtim = ((avp->av_boff.bo_tim[2] == 1) ||
(avp->av_boff.bo_tim[3] == 1));

View File

@ -0,0 +1,13 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -539,8 +539,8 @@ ath_attach(u_int16_t devid, struct net_d
/* Allocate space for dynamically determined maximum VAP count */
sc->sc_bslot =
- kmalloc(ath_maxvaps * sizeof(struct ieee80211vap), GFP_KERNEL);
- memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap));
+ kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
+ memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap*));
/*
* Cache line size is used to size and align various

View File

@ -0,0 +1,10 @@
--- a/net80211/ieee80211.c
+++ b/net80211/ieee80211.c
@@ -684,6 +684,7 @@ ieee80211_find_channel(struct ieee80211c
int i;
/* Brute force search */
+ flags &= IEEE80211_CHAN_ALLTURBO;
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
if (c->ic_freq == freq &&

View File

@ -0,0 +1,52 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -389,6 +389,7 @@ static int ath_countrycode = CTRY_DEFAUL
static int ath_outdoor = AH_FALSE; /* enable outdoor use */
static int ath_xchanmode = AH_TRUE; /* enable extended channels */
static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */
+static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */
static char *autocreate = NULL;
static char *ratectl = DEF_RATE_CTL;
static int rfkill = 0;
@@ -432,6 +433,7 @@ MODULE_PARM(rfkill, "i");
#ifdef ATH_CAP_TPC
MODULE_PARM(tpc, "i");
#endif
+MODULE_PARM(bstuck_thresh, "i");
MODULE_PARM(autocreate, "s");
MODULE_PARM(ratectl, "s");
#else
@@ -445,6 +447,7 @@ module_param(rfkill, int, 0600);
#ifdef ATH_CAP_TPC
module_param(tpc, int, 0600);
#endif
+module_param(bstuck_thresh, int, 0600);
module_param(autocreate, charp, 0600);
module_param(ratectl, charp, 0600);
#endif
@@ -457,6 +460,7 @@ MODULE_PARM_DESC(rfkill, "Enable/disable
MODULE_PARM_DESC(tpc, "Enable/disable per-packet transmit power control (TPC) "
"capability");
#endif
+MODULE_PARM_DESC(bstuck_thresh, "Override default stuck beacon threshold");
MODULE_PARM_DESC(autocreate, "Create ath device in "
"[sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use "
"'none' to disable");
@@ -5072,7 +5076,7 @@ ath_beacon_send(struct ath_softc *sc, in
DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
"Missed %u consecutive beacons (n_beacon=%u)\n",
sc->sc_bmisscount, n_beacon);
- if (sc->sc_bmisscount > BSTUCK_THRESH)
+ if (sc->sc_bmisscount > bstuck_thresh)
ATH_SCHEDULE_TQUEUE(&sc->sc_bstucktq, needmark);
return;
}
@@ -5230,7 +5234,7 @@ ath_bstuck_tasklet(TQUEUE_ARG data)
* check will be true, in which case return
* without resetting the driver.
*/
- if (sc->sc_bmisscount <= BSTUCK_THRESH)
+ if (sc->sc_bmisscount <= bstuck_thresh)
return;
EPRINTF(sc, "Stuck beacon; resetting (beacon miss count: %u)\n",
sc->sc_bmisscount);

View File

@ -0,0 +1,77 @@
Patch adapted from ubnt madwifi patchset
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -659,7 +659,7 @@ ieee80211_sta_join1(struct ieee80211_nod
*/
if (canreassoc) {
vap->iv_nsparams.newstate = IEEE80211_S_ASSOC;
- vap->iv_nsparams.arg = 0;
+ vap->iv_nsparams.arg = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
IEEE80211_SCHEDULE_TQUEUE(&vap->iv_stajoin1tq);
} else {
vap->iv_nsparams.newstate = IEEE80211_S_AUTH;
--- a/net80211/ieee80211_scan_sta.c
+++ b/net80211/ieee80211_scan_sta.c
@@ -748,14 +748,17 @@ notfound:
* a reference to an entry w/o holding the lock on the table.
*/
static struct sta_entry *
-sta_lookup(struct sta_table *st, const u_int8_t macaddr[IEEE80211_ADDR_LEN])
+sta_lookup(struct sta_table *st, const u_int8_t macaddr[IEEE80211_ADDR_LEN], struct ieee80211_scan_ssid* essid)
{
struct sta_entry *se;
int hash = STA_HASH(macaddr);
SCAN_STA_LOCK_IRQ(st);
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
- if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
+ if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) &&
+ (essid->len == se->base.se_ssid[1] &&
+ !memcmp(se->base.se_ssid+2, essid->ssid,
+ se->base.se_ssid[1])))
break;
SCAN_STA_UNLOCK_IRQ(st);
@@ -772,7 +775,7 @@ sta_roam_check(struct ieee80211_scan_sta
u_int8_t roamRate, curRate;
int8_t roamRssi, curRssi;
- se = sta_lookup(st, ni->ni_macaddr);
+ se = sta_lookup(st, ni->ni_macaddr, ss->ss_ssid);
if (se == NULL) {
/* XXX something is wrong */
return;
@@ -866,8 +869,8 @@ sta_age(struct ieee80211_scan_state *ss)
*/
KASSERT(vap->iv_opmode == IEEE80211_M_STA,
("wrong mode %u", vap->iv_opmode));
- /* XXX turn this off until the ap release is cut */
- if (0 && vap->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO &&
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ vap->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO &&
vap->iv_state >= IEEE80211_S_RUN)
/* XXX vap is implicit */
sta_roam_check(ss, vap);
@@ -922,7 +925,11 @@ sta_assoc_fail(struct ieee80211_scan_sta
struct sta_table *st = ss->ss_priv;
struct sta_entry *se;
- se = sta_lookup(st, macaddr);
+ /* Let outside apps to decide what peer is blacklisted */
+ if (ss->ss_vap->iv_ic->ic_roaming == IEEE80211_ROAMING_MANUAL)
+ return;
+
+ se = sta_lookup(st, macaddr, ss->ss_ssid);
if (se != NULL) {
se->se_fails++;
se->se_lastfail = jiffies;
@@ -939,7 +946,7 @@ sta_assoc_success(struct ieee80211_scan_
struct sta_table *st = ss->ss_priv;
struct sta_entry *se;
- se = sta_lookup(st, macaddr);
+ se = sta_lookup(st, macaddr, ss->ss_ssid);
if (se != NULL) {
#if 0
se->se_fails = 0;

View File

@ -0,0 +1,49 @@
--- a/net80211/ieee80211_scan_sta.c
+++ b/net80211/ieee80211_scan_sta.c
@@ -201,8 +201,10 @@ sta_flush_table(struct sta_table *st)
}
static void
-saveie(u_int8_t **iep, const u_int8_t *ie)
+saveie(u_int8_t **iep, const u_int8_t *ie, int preserve)
{
+ if (preserve && *iep)
+ return;
if (ie == NULL)
*iep = NULL;
else
@@ -304,10 +306,10 @@ found:
(const struct ieee80211_tim_ie *) sp->tim;
ise->se_dtimperiod = tim->tim_period;
}
- saveie(&ise->se_wme_ie, sp->wme);
- saveie(&ise->se_wpa_ie, sp->wpa);
- saveie(&ise->se_rsn_ie, sp->rsn);
- saveie(&ise->se_ath_ie, sp->ath);
+ saveie(&ise->se_wme_ie, sp->wme, 0);
+ saveie(&ise->se_wpa_ie, sp->wpa, !sp->isprobe);
+ saveie(&ise->se_rsn_ie, sp->rsn, !sp->isprobe);
+ saveie(&ise->se_ath_ie, sp->ath, 0);
/* clear failure count after STA_FAIL_AGE passes */
if (se->se_fails && (jiffies - se->se_lastfail) > STA_FAILS_AGE*HZ) {
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3106,6 +3106,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
*/
IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
memset(&scan, 0, sizeof(scan));
+ scan.isprobe = (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) && IEEE80211_ADDR_EQ(wh->i_addr2, vap->iv_myaddr);
scan.tstamp = frm;
frm += 8;
scan.bintval = le16toh(*(__le16 *)frm);
--- a/net80211/ieee80211_scan.h
+++ b/net80211/ieee80211_scan.h
@@ -133,6 +133,7 @@ struct ieee80211_scanparams {
u_int8_t erp;
u_int16_t bintval;
u_int8_t timoff;
+ u_int8_t isprobe;
u_int8_t *tim;
u_int8_t *tstamp;
u_int8_t *country;

View File

@ -0,0 +1,10 @@
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -3723,6 +3723,7 @@ ieee80211_ioctl_setmlme(struct net_devic
if (vap->iv_opmode == IEEE80211_M_STA) {
struct scanlookup lookup;
+ preempt_scan(dev, 100, 100);
lookup.se = NULL;
lookup.mac = mlme->im_macaddr;
/* XXX use revised api w/ explicit ssid */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -1198,6 +1198,7 @@ ieee80211_deliver_data(struct ieee80211_
}
if (skb1 != NULL) {
struct ieee80211_node *ni_tmp;
+ int ret;
skb1->dev = dev;
skb_reset_mac_header(skb1);
skb_set_network_header(skb1, sizeof(struct ether_header));
@@ -1205,7 +1206,12 @@ ieee80211_deliver_data(struct ieee80211_
skb1->protocol = __constant_htons(ETH_P_802_2);
/* XXX insert vlan tag before queue it? */
ni_tmp = SKB_CB(skb1)->ni; /* remember node so we can free it */
- if (dev_queue_xmit(skb1) == NET_XMIT_DROP) {
+ ret = dev->hard_start_xmit(skb1, dev);
+
+ if (ret == NETDEV_TX_BUSY)
+ ieee80211_dev_kfree_skb(&skb1);
+
+ else if (ret != NETDEV_TX_OK) {
/* If queue dropped the packet because device was
* too busy */
vap->iv_devstats.tx_dropped++;
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -324,9 +324,10 @@ void ieee80211_parent_queue_xmit(struct
/* Dispatch the packet to the parent device */
skb->dev = vap->iv_ic->ic_dev;
- if (dev_queue_xmit(skb) == NET_XMIT_DROP)
+ if (netif_queue_stopped(skb->dev))
+ ieee80211_dev_kfree_skb(&skb);
+ else if (dev_queue_xmit(skb) == NET_XMIT_DROP)
vap->iv_devstats.tx_dropped++;
-
}
/*

View File

@ -0,0 +1,12 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -250,6 +250,9 @@ ieee80211_input(struct ieee80211vap * va
if (vap->iv_opmode == IEEE80211_M_MONITOR)
goto out;
+ if (!skb->data)
+ goto out;
+
if (skb->len < sizeof(struct ieee80211_frame_min)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
ni->ni_macaddr, NULL,

View File

@ -0,0 +1,22 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -5486,6 +5486,9 @@ ath_beacon_config(struct ath_softc *sc,
ath_beacon_dturbo_config(vap, intval &
~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA));
#endif
+ if ((nexttbtt & HAL_BEACON_PERIOD) - (ath_hal_gettsf32(ah) >> 10)
+ <= ath_hal_sw_beacon_response_time)
+ nexttbtt += intval;
sc->sc_nexttbtt = nexttbtt;
ath_hal_beaconinit(ah, nexttbtt, intval);
if (intval & HAL_BEACON_RESET_TSF) {
--- a/ath_hal/ah_os.c
+++ b/ath_hal/ah_os.c
@@ -71,6 +71,7 @@ static int ath_hal_debug = 99;
int ath_hal_dma_beacon_response_time = 2; /* in TUs */
int ath_hal_sw_beacon_response_time = 10; /* in TUs */
int ath_hal_additional_swba_backoff = 0; /* in TUs */
+EXPORT_SYMBOL(ath_hal_sw_beacon_response_time);
struct ath_hal *
_ath_hal_attach(u_int16_t devid, HAL_SOFTC sc,

View File

@ -0,0 +1,141 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -161,6 +161,7 @@ static void ath_beacon_send(struct ath_s
static void ath_beacon_return(struct ath_softc *, struct ath_buf *);
static void ath_beacon_free(struct ath_softc *);
static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
+static void ath_hw_beacon_stop(struct ath_softc *sc);
static int ath_desc_alloc(struct ath_softc *);
static void ath_desc_free(struct ath_softc *);
static void ath_desc_swap(struct ath_desc *);
@@ -2793,6 +2794,72 @@ ath_set_ack_bitrate(struct ath_softc *sc
return 1;
}
+static void
+ath_hw_beacon_stop(struct ath_softc *sc)
+{
+ HAL_BEACON_TIMERS btimers;
+
+ btimers.bt_intval = 0;
+ btimers.bt_nexttbtt = 0;
+ btimers.bt_nextdba = 0xffffffff;
+ btimers.bt_nextswba = 0xffffffff;
+ btimers.bt_nextatim = 0;
+
+ ath_hal_setbeacontimers(sc->sc_ah, &btimers);
+}
+
+/* Fix up the ATIM window after TSF resync */
+static int
+ath_hw_check_atim(struct ath_softc *sc, int window, int intval)
+{
+#define AR5K_TIMER0_5210 0x802c /* Next beacon time register */
+#define AR5K_TIMER0_5211 0x8028
+#define AR5K_TIMER3_5210 0x8038 /* End of ATIM window time register */
+#define AR5K_TIMER3_5211 0x8034
+ struct ath_hal *ah = sc->sc_ah;
+ int dev = sc->sc_ah->ah_macType;
+ unsigned int nbtt, atim;
+ int is_5210 = 0;
+
+ /*
+ * check if the ATIM window is still correct:
+ * 1.) usually ATIM should be NBTT + window
+ * 2.) nbtt already updated
+ * 3.) nbtt already updated and has wrapped around
+ * 4.) atim has wrapped around
+ */
+ switch(dev) {
+ case 5210:
+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
+ atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
+ is_5210 = 1;
+ break;
+ case 5211:
+ case 5212:
+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
+ atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
+ break;
+ /* NB: 5416+ doesn't do ATIM in hw */
+ case 5416:
+ default:
+ return 0;
+ }
+
+ if ((atim - nbtt != window) && /* 1.) */
+ (nbtt - atim != intval - window) && /* 2.) */
+ ((nbtt | 0x10000) - atim != intval - window) && /* 3.) */
+ ((atim | 0x10000) - nbtt != window)) { /* 4.) */
+ if (is_5210)
+ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
+ else
+ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
+ return atim - nbtt;
+ }
+
+ return 0;
+}
+
+
/*
* Reset the hardware w/o losing operational state. This is
* basically a more efficient way of doing ath_stop, ath_init,
@@ -5294,6 +5361,7 @@ ath_beacon_config(struct ath_softc *sc,
u_int64_t tsf, hw_tsf;
u_int32_t tsftu, hw_tsftu;
u_int32_t intval, nexttbtt = 0;
+ unsigned long flags;
int reset_tsf = 0;
if (vap == NULL)
@@ -5301,6 +5369,9 @@ ath_beacon_config(struct ath_softc *sc,
ni = vap->iv_bss;
+ /* TSF calculation is timing critical - we don't want to be interrupted here */
+ local_irq_save(flags);
+
hw_tsf = ath_hal_gettsf64(ah);
tsf = le64_to_cpu(ni->ni_tstamp.tsf);
hw_tsftu = hw_tsf >> 10;
@@ -5490,15 +5561,27 @@ ath_beacon_config(struct ath_softc *sc,
<= ath_hal_sw_beacon_response_time)
nexttbtt += intval;
sc->sc_nexttbtt = nexttbtt;
+
+ /* stop beacons before reconfiguring the timers to avoid race
+ * conditions. ath_hal_beaconinit will start them again */
+ ath_hw_beacon_stop(sc);
+
ath_hal_beaconinit(ah, nexttbtt, intval);
if (intval & HAL_BEACON_RESET_TSF) {
sc->sc_last_tsf = 0;
}
sc->sc_bmisscount = 0;
ath_hal_intrset(ah, sc->sc_imask);
+
+ if ((sc->sc_opmode == HAL_M_IBSS) && ath_hw_check_atim(sc, 1, intval & HAL_BEACON_PERIOD)) {
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "fixed atim window after beacon init\n");
+ }
}
ath_beacon_config_debug:
+ local_irq_restore(flags);
+
/* We print all debug messages here, in order to preserve the
* time critical aspect of this function */
DPRINTF(sc, ATH_DEBUG_BEACON,
@@ -6401,6 +6484,11 @@ ath_recv_mgmt(struct ieee80211vap * vap,
DPRINTF(sc, ATH_DEBUG_BEACON,
"Updated beacon timers\n");
}
+ if ((sc->sc_opmode == HAL_M_IBSS) &&
+ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
+ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
+ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
+ }
/* NB: Fall Through */
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
if (vap->iv_opmode == IEEE80211_M_IBSS &&

View File

@ -0,0 +1,25 @@
--- a/net80211/ieee80211_linux.h
+++ b/net80211/ieee80211_linux.h
@@ -657,22 +657,7 @@ int ieee80211_proc_vcreate(struct ieee80
char *);
void ieee80211_proc_cleanup(struct ieee80211vap *);
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define IEEE80211_VLAN_TAG_USED 1
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)
-#define vlan_hwaccel_receive_skb(skb, grp, tag) vlan_hwaccel_rx(skb, grp, tag)
-#endif
-
-#ifndef VLAN_GROUP_ARRAY_PART_LEN
-#define vlan_group_set_device(group, vid, dev) do { \
- group->vlan_devices[vid] = dev; \
-} while (0);
-#endif
-
-#else
#define IEEE80211_VLAN_TAG_USED 0
-#endif
void ieee80211_vlan_vattach(struct ieee80211vap *);
void ieee80211_vlan_vdetach(struct ieee80211vap *);

View File

@ -0,0 +1,14 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3529,6 +3529,11 @@ ieee80211_recv_mgmt(struct ieee80211vap
if (ic->ic_flags & IEEE80211_F_SCAN) {
ieee80211_add_scan(vap, &scan, wh, subtype, rssi, rtsf);
}
+
+ /* stop processing if the bss channel is not set up yet */
+ if (!ic->ic_bsschan || ic->ic_bsschan == IEEE80211_CHAN_ANYC)
+ break;
+
/* NB: Behavior of WDS-Link and Ad-Hoc is very similar here:
* When we receive a beacon that belongs to the AP that we're
* connected to, use it to refresh the local node info.

View File

@ -0,0 +1,405 @@
--- a/ath_rate/minstrel/minstrel.c
+++ b/ath_rate/minstrel/minstrel.c
@@ -111,27 +111,13 @@
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_rate.h>
+#include "if_ath_debug.h"
#include "if_athvar.h"
#include "if_ath_hal.h"
#include "ah_desc.h"
#include "minstrel.h"
-#ifdef AR_DEBUG
-#define MINSTREL_DEBUG
-#endif
-#ifdef MINSTREL_DEBUG
-enum {
- ATH_DEBUG_RATE = 0x00000010 /* rate control */
-};
-#define DPRINTF(sc, _fmt, ...) do { \
- if (sc->sc_debug & ATH_DEBUG_RATE) \
- printk(_fmt, __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(sc, _fmt, ...)
-#endif
-
#define ONE_SECOND (1000 * 1000) /* 1 second, or 1000 milliseconds; eternity, in other words */
#include "release.h"
@@ -471,11 +457,11 @@ ath_rate_tx_complete(struct ath_softc *s
final_rate = sc->sc_hwmap[ts->ts_rate & ~HAL_TXSTAT_ALTRATE].ieeerate;
final_ndx = rate_to_ndx(sn, final_rate);
if (final_ndx >= sn->num_rates) {
- DPRINTF(sc, "%s: final ndx too high\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: final ndx too high\n", __func__);
final_ndx = 0;
}
if (final_ndx < 0) {
- DPRINTF(sc, "%s: final ndx too low\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: final ndx too low\n", __func__);
final_ndx = 0;
}
@@ -485,7 +471,7 @@ ath_rate_tx_complete(struct ath_softc *s
tries = ts->ts_longretry + 1;
if (sn->num_rates <= 0) {
- DPRINTF(sc, "%s: " MAC_FMT " %s no rates yet\n", dev_info,
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " %s no rates yet\n", dev_info,
MAC_ADDR(an->an_node.ni_macaddr), __func__);
return;
}
@@ -551,7 +537,7 @@ ath_rate_tx_complete(struct ath_softc *s
static void
ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
{
- DPRINTF(sc, "%s: " MAC_FMT " %s\n", dev_info,
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " %s\n", dev_info,
MAC_ADDR(an->an_node.ni_macaddr), __func__);
if (isnew)
ath_rate_ctl_reset(sc, &an->an_node);
@@ -601,7 +587,7 @@ ath_fill_sample_table(struct minstrel_no
p = rates + sprintf(rates, "rates :: %d ", column_index);
for (i = 0; i < num_sample_rates; i++)
p += sprintf(p, "%2u ", sn->rs_sampleTable[i][column_index]);
- DPRINTF(sc, "%s\n", rates);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s\n", rates);
};
#endif
}
@@ -628,7 +614,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
sn->is_sampling = 0;
if (rt == NULL) {
- DPRINTF(sc, "no rates yet! mode %u\n", sc->sc_curmode);
+ DPRINTF(sc, ATH_DEBUG_RATE, "no rates yet! mode %u\n", sc->sc_curmode);
return;
}
sn->static_rate_ndx = -1;
@@ -658,7 +644,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
}
if (sn->rates[x].rix == 0xff) {
- DPRINTF(sc, "%s: %s ignore bogus rix at %d\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %d\n",
dev_info, __func__, x);
continue;
}
@@ -673,7 +659,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
ni->ni_txrate = 0;
if (sn->num_rates <= 0) {
- DPRINTF(sc, "%s: %s " MAC_FMT " no rates (fixed %d) \n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " no rates (fixed %d) \n",
dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
vap->iv_fixed_rate);
/* There are no rates yet; we're done */
@@ -689,23 +675,23 @@ ath_rate_ctl_reset(struct ath_softc *sc,
* the node. We know the rate is there because the
* rate set is checked when the station associates. */
/* NB: the rate set is assumed sorted */
- for (; (srate >= 0) && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--);
-
- KASSERT(srate >= 0,
- ("fixed rate %d not in rate set", vap->iv_fixed_rate));
+ for (; (srate > 0) && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--);
sn->static_rate_ndx = srate;
ni->ni_txrate = srate;
- DPRINTF(sc, "%s: %s " MAC_FMT " fixed rate %d%sMbps\n",
- dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
- sn->rates[srate].rate / 2,
- (sn->rates[srate].rate % 2) ? ".5 " : " ");
+ if ((ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate)
+ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
+ else
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " fixed rate %d%sMbps\n",
+ dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
+ sn->rates[srate].rate / 2,
+ (sn->rates[srate].rate % 2) ? ".5 " : " ");
return;
}
for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
if (sn->rates[x].rix == 0xff) {
- DPRINTF(sc, "%s: %s ignore bogus rix at %d\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %d\n",
dev_info, __func__, x);
continue;
}
@@ -735,9 +721,9 @@ ath_rate_ctl_reset(struct ath_softc *sc,
}
#if 0
- DPRINTF(sc, "%s: Retry table for this node\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: Retry table for this node\n", __func__);
for (x = 0; x < ni->ni_rates.rs_nrates; x++)
- DPRINTF(sc, "%2d %2d %6d \n", x, sn->retry_count[x], sn->perfect_tx_time[x]);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%2d %2d %6d \n", x, sn->retry_count[x], sn->perfect_tx_time[x]);
#endif
/* Set the initial rate */
@@ -781,10 +767,10 @@ ath_timer_function(unsigned long data)
unsigned int interval = ath_timer_interval;
if (dev == NULL)
- DPRINTF(sc, "%s: 'dev' is null in this timer \n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'dev' is null in this timer \n", __func__);
if (sc == NULL)
- DPRINTF(sc, "%s: 'sc' is null in this timer\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'sc' is null in this timer\n", __func__);
ic = &sc->sc_ic;
@@ -808,7 +794,7 @@ ath_timer_function(unsigned long data)
timer = &(ssc->timer);
if (timer == NULL)
- DPRINTF(sc, "%s: timer is null - leave it\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: timer is null - leave it\n", __func__);
timer->expires = jiffies + ((HZ * interval) / 1000);
add_timer(timer);
@@ -904,7 +890,7 @@ static struct ath_ratectrl *
ath_rate_attach(struct ath_softc *sc)
{
struct minstrel_softc *osc;
- DPRINTF(sc, "%s: %s\n", dev_info, __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s\n", dev_info, __func__);
_MOD_INC_USE(THIS_MODULE, return NULL);
osc = kmalloc(sizeof(struct minstrel_softc), GFP_ATOMIC);
@@ -963,7 +949,7 @@ ath_proc_read_nodes(struct ieee80211vap
p += sprintf(p, "out of room for node " MAC_FMT "\n\n", MAC_ADDR(ni->ni_macaddr));
break;
}
- DPRINTF(sc, "%s: out of memeory to write tall of the nodes\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: out of memeory to write tall of the nodes\n", __func__);
break;
}
an = ATH_NODE(ni);
--- a/ath_rate/amrr/amrr.c
+++ b/ath_rate/amrr/amrr.c
@@ -64,24 +64,13 @@
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_rate.h>
+#include "if_ath_debug.h"
#include "if_athvar.h"
#include "if_ath_hal.h"
#include "ah_desc.h"
#include "amrr.h"
-#ifdef AR_DEBUG
-#define AMRR_DEBUG
-#endif
-#ifdef AMRR_DEBUG
-#define DPRINTF(sc, _fmt, ...) do { \
- if (sc->sc_debug & 0x10) \
- printk(_fmt, __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(sc, _fmt, ...)
-#endif
-
static int ath_rateinterval = 1000; /* rate ctl interval (ms) */
static int ath_rate_max_success_threshold = 10;
static int ath_rate_min_success_threshold = 1;
@@ -197,7 +186,7 @@ ath_rate_update(struct ath_softc *sc, st
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
- DPRINTF(sc, "%s: set xmit rate for " MAC_FMT " to %dM\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: set xmit rate for " MAC_FMT " to %dM\n",
__func__, MAC_ADDR(ni->ni_macaddr),
ni->ni_rates.rs_nrates > 0 ?
(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
@@ -297,9 +286,9 @@ ath_rate_ctl_start(struct ath_softc *sc,
* rate set is checked when the station associates.
*/
srate = ni->ni_rates.rs_nrates - 1;
- for (; srate >= 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
- KASSERT(srate >= 0,
- ("fixed rate %d not in rate set", vap->iv_fixed_rate));
+ for (; srate > 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
+ if (RATE(srate) != vap->iv_fixed_rate)
+ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
}
ath_rate_update(sc, ni, srate);
#undef RATE
@@ -377,7 +366,7 @@ ath_rate_ctl(void *arg, struct ieee80211
old_rate = ni->ni_txrate;
- DPRINTF (sc, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n",
amn->amn_tx_try0_cnt,
amn->amn_tx_try1_cnt,
amn->amn_tx_try2_cnt,
@@ -390,7 +379,7 @@ ath_rate_ctl(void *arg, struct ieee80211
amn->amn_recovery = 1;
amn->amn_success = 0;
ni->ni_txrate++;
- DPRINTF(sc, "increase rate to %d\n", ni->ni_txrate);
+ DPRINTF(sc, ATH_DEBUG_RATE, "increase rate to %d\n", ni->ni_txrate);
} else
amn->amn_recovery = 0;
} else if (is_failure(amn)) {
@@ -401,12 +390,12 @@ ath_rate_ctl(void *arg, struct ieee80211
amn->amn_success_threshold *= 2;
amn->amn_success_threshold = min(amn->amn_success_threshold,
(u_int)ath_rate_max_success_threshold);
- DPRINTF(sc, "decrease rate recovery thr: %d\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "decrease rate recovery thr: %d\n",
amn->amn_success_threshold);
} else {
/* simple failure. */
amn->amn_success_threshold = ath_rate_min_success_threshold;
- DPRINTF(sc, "decrease rate normal thr: %d\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "decrease rate normal thr: %d\n",
amn->amn_success_threshold);
}
amn->amn_recovery = 0;
--- a/ath_rate/onoe/onoe.c
+++ b/ath_rate/onoe/onoe.c
@@ -60,27 +60,13 @@
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_rate.h>
+#include "if_ath_debug.h"
#include "if_athvar.h"
#include "if_ath_hal.h"
#include "ah_desc.h"
#include "onoe.h"
-#ifdef AR_DEBUG
-#define ONOE_DEBUG
-#endif
-#ifdef ONOE_DEBUG
-enum {
- ATH_DEBUG_RATE = 0x00000010, /* rate control */
-};
-#define DPRINTF(sc, _fmt, ...) do { \
- if (sc->sc_debug & ATH_DEBUG_RATE) \
- printk(_fmt, __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(sc, _fmt, ...)
-#endif
-
/*
* Default parameters for the rate control algorithm. These are
* all tunable with sysctls. The rate controller runs periodically
@@ -186,7 +172,7 @@ ath_rate_update(struct ath_softc *sc, st
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
- DPRINTF(sc, "%s: set xmit rate for " MAC_FMT " to %dM\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: set xmit rate for " MAC_FMT " to %dM\n",
__func__, MAC_ADDR(ni->ni_macaddr),
ni->ni_rates.rs_nrates > 0 ?
(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
@@ -283,9 +269,9 @@ ath_rate_ctl_start(struct ath_softc *sc,
*/
/* NB: the rate set is assumed sorted */
srate = ni->ni_rates.rs_nrates - 1;
- for (; srate >= 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
- KASSERT(srate >= 0,
- ("fixed rate %d not in rate set", vap->iv_fixed_rate));
+ for (; srate > 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
+ if (RATE(srate) != vap->iv_fixed_rate)
+ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
}
ath_rate_update(sc, ni, srate);
#undef RATE
@@ -364,7 +350,7 @@ ath_rate_ctl(void *arg, struct ieee80211
on->on_tx_retr < (on->on_tx_ok * ath_rate_raise) / 100)
dir = 1;
- DPRINTF(sc, MAC_FMT ": ok %d err %d retr %d upper %d dir %d\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, MAC_FMT ": ok %d err %d retr %d upper %d dir %d\n",
MAC_ADDR(ni->ni_macaddr),
on->on_tx_ok, on->on_tx_err, on->on_tx_retr,
on->on_tx_upper, dir);
@@ -395,7 +381,7 @@ ath_rate_ctl(void *arg, struct ieee80211
}
if (nrate != ni->ni_txrate) {
- DPRINTF(sc, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
__func__,
(rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2,
(rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2,
--- a/ath_rate/sample/sample.c
+++ b/ath_rate/sample/sample.c
@@ -62,30 +62,13 @@
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_rate.h>
+#include "if_ath_debug.h"
#include "if_athvar.h"
#include "if_ath_hal.h"
#include "ah_desc.h"
#include "sample.h"
-#ifdef AR_DEBUG
-#define SAMPLE_DEBUG
-#endif
-#ifdef SAMPLE_DEBUG
-enum {
- ATH_DEBUG_RATE = 0x00000010, /* rate control */
- ATH_DEBUG_ANY = 0xffffffff
-};
-#define DPRINTF(sc, m, fmt, ...) do { \
- if (sc->sc_debug & (m)) \
- printk(fmt, __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(sc, m, fmt, ...) do { \
- (void) sc; \
-} while (0)
-#endif
-
/*
* This file is an implementation of the SampleRate algorithm
* in "Bit-rate Selection in Wireless Networks"
@@ -740,7 +723,7 @@ ath_rate_tx_complete(struct ath_softc *s
ndx[3] = rate_to_ndx(sn, rate[3]);
#if 0
- DPRINTF(sc, "%s: " MAC_FMT " size %u finaltsidx %u tries %u status %u rate/try %u/%u %u/%u %u/%u %u/%u\n",
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " size %u finaltsidx %u tries %u status %u rate/try %u/%u %u/%u %u/%u %u/%u\n",
dev_info, MAC_ADDR(an->an_node.ni_macaddr),
bin_to_size(size_to_bin(frame_size)),
finalTSIdx,
@@ -886,15 +869,16 @@ ath_rate_ctl_reset(struct ath_softc *sc,
if ((ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL) == vap->iv_fixed_rate)
srate = x;
- KASSERT(((ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) == vap->iv_fixed_rate),
- ("fixed rate %u not in rate set", vap->iv_fixed_rate));
-
sn->static_rate_ndx = srate;
ni->ni_txrate = srate;
- DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " fixed rate %u%sMbps\n",
- dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
- sn->rates[srate].rate / 2,
- (sn->rates[srate].rate % 0x1) ? ".5" : " ");
+
+ if ((ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate)
+ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
+ else
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " fixed rate %u%sMbps\n",
+ dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
+ sn->rates[srate].rate / 2,
+ (sn->rates[srate].rate % 0x1) ? ".5" : " ");
return;
}

View File

@ -0,0 +1,13 @@
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -427,8 +427,8 @@ ieee80211_reset_bss(struct ieee80211vap
__func__, ni, MAC_ADDR(vap->iv_myaddr));
KASSERT(ni != NULL, ("unable to setup inital BSS node"));
- vap->iv_bss = PASS_NODE(ni);
- KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 2),
+ vap->iv_bss = ieee80211_ref_node(ni);
+ KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 3),
("wrong refcount for new node."));
if (obss != NULL) {

View File

@ -0,0 +1,23 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1260,7 +1260,10 @@ ath_vap_create(struct ieee80211com *ic,
case IEEE80211_M_IBSS:
if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA))
return NULL;
- ic_opmode = opmode;
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ ic_opmode = ic->ic_opmode;
+ else
+ ic_opmode = opmode;
break;
case IEEE80211_M_AHDEMO:
case IEEE80211_M_MONITOR:
@@ -1455,7 +1458,7 @@ ath_vap_create(struct ieee80211com *ic,
* frames. Other modes carry over directly to the HAL.
*/
if (ic->ic_opmode == IEEE80211_M_AHDEMO)
- sc->sc_opmode = HAL_M_IBSS;
+ sc->sc_opmode = HAL_M_HOSTAP;
else
sc->sc_opmode = (HAL_OPMODE) ic->ic_opmode; /* NB: compatible */

View File

@ -0,0 +1,13 @@
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -61,8 +61,8 @@
#define IEEE80211_DTIM_MIN 1 /* min DTIM period */
#define IEEE80211_DTIM_DEFAULT 1 /* default DTIM period */
-#define IEEE80211_BINTVAL_MAX 1000 /* max beacon interval (TUs) */
-#define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TUs) */
+#define IEEE80211_BINTVAL_MAX 5000 /* max beacon interval (TUs) */
+#define IEEE80211_BINTVAL_MIN 10 /* min beacon interval (TUs) */
#define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TUs) */
#define IEEE80211_BINTVAL_VALID(_bi) \
((IEEE80211_BINTVAL_MIN <= (_bi)) && \

View File

@ -0,0 +1,105 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -1452,6 +1452,23 @@ ath_vap_create(struct ieee80211com *ic,
sc->sc_nstavaps++;
else if (opmode == IEEE80211_M_MONITOR)
sc->sc_nmonvaps++;
+
+
+ /* Driving the HAL in IBSS sometimes adapts the TSF and other timing registers
+ * from received beacons/probes. If that happens, expected TX interrupts may
+ * not occur until next reset. Which triggers the "lost beacon" tasklet.
+ * Resulting effectively in not sending packets for minutes. Because that only
+ * happens in large mesh networks, this mode needs to be activated by a kernel
+ * module parameter: hostap_for_ibss=1. Note that using this mode has side
+ * effects. Such as not supressing beacons/probe answers randomly when
+ * receiving other node beacons. It's recommended to lower the beacon interval
+ * then. When using an IBSS-VAP together with an HOSTAP-VAP, you may also need
+ * to re-trigger IBSS beacon generation after creating the HOSTAP-VAP by
+ * issueing "iwpriv athX bintval 1000".
+ */
+ if ((flags & IEEE80211_NO_STABEACONS) && (ic->ic_opmode == IEEE80211_M_IBSS))
+ sc->sc_opmode = HAL_M_HOSTAP;
+ else
/*
* Adhoc demo mode is a pseudo mode; to the HAL it's
* just IBSS mode and the driver doesn't use management
@@ -4279,7 +4296,8 @@ ath_calcrxfilter(struct ath_softc *sc)
if (ic->ic_opmode != IEEE80211_M_HOSTAP && (dev->flags & IFF_PROMISC))
rfilt |= HAL_RX_FILTER_PROM;
if (ic->ic_opmode == IEEE80211_M_STA ||
- sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */
+ ic->ic_opmode == IEEE80211_M_IBSS ||
+ ic->ic_opmode == IEEE80211_M_AHDEMO ||
(sc->sc_nostabeacons) || sc->sc_scanning ||
(ic->ic_opmode == IEEE80211_M_HOSTAP))
rfilt |= HAL_RX_FILTER_BEACON;
@@ -6435,6 +6453,33 @@ ath_capture(struct net_device *dev, cons
}
/*
+ * Advances (forwards/adds) a microsecond value to current chip's TSF registers
+ */
+
+/* from ath_info.c */
+#define AR5K_TSF_L32_5210 0x806c /* TSF (lower 32 bits) */
+#define AR5K_TSF_L32_5211 0x804c
+#define AR5K_TSF_L32 (ar_device(ah->ah_sc->devid) == 5210 ? \
+ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
+
+#define AR5K_TSF_U32_5210 0x8070
+#define AR5K_TSF_U32_5211 0x8050
+#define AR5K_TSF_U32 (ar_device(ah->ah_sc->devid) == 5210 ? \
+ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
+
+static inline void ath_hal_settsf64(struct ath_hal *ah, u_int64_t tsf_adv)
+{
+ ATH_HAL_LOCK_IRQ(ah->ah_sc);
+ ath_hal_set_function(__func__);
+ tsf_adv += ah->ah_getTsf64(ah);
+ OS_REG_WRITE(ah, AR5K_TSF_L32, 0ll);
+ OS_REG_WRITE(ah, AR5K_TSF_U32, (tsf_adv >> 32) & 0xffffffffll);
+ OS_REG_WRITE(ah, AR5K_TSF_L32, (tsf_adv >> 00) & 0xffffffffll);
+ ath_hal_set_function(NULL);
+ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+}
+
+/*
* Intercept management frames to collect beacon RSSI data and to do
* ibss merges. This function is called for all management frames,
* including those belonging to other BSS.
@@ -6487,10 +6532,19 @@ ath_recv_mgmt(struct ieee80211vap * vap,
DPRINTF(sc, ATH_DEBUG_BEACON,
"Updated beacon timers\n");
}
- if ((sc->sc_opmode == HAL_M_IBSS) &&
- IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
- ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
- DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
+ if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+ (sc->sc_opmode == HAL_M_HOSTAP) &&
+ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
+ /* In this mode, we drive the HAL in HOSTAP mode. Hence
+ * we do the IBSS merging in software. Also do not merge
+ * if the difference it too small. Otherwise we are playing
+ * tsf-pingpong with other vendors drivers */
+ beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
+ if (beacon_tsf > rtsf + 0xffff) {
+ ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf);
+ ieee80211_ibss_merge(ni);
+ }
+ break;
}
/* NB: Fall Through */
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
@@ -6563,6 +6617,10 @@ ath_recv_mgmt(struct ieee80211vap * vap,
#endif
if (do_merge)
ieee80211_ibss_merge(ni);
+
+ if ((sc->sc_opmode == HAL_M_IBSS) &&
+ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval))
+ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
}
break;
}

View File

@ -0,0 +1,325 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -62,6 +62,7 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/time.h>
+#include <linux/pci.h>
#include <asm/uaccess.h>
#include "if_ethersubr.h" /* for ETHER_IS_MULTICAST */
@@ -401,6 +402,15 @@ static int outdoor = -1;
static int xchanmode = -1;
static int beacon_cal = 1;
+static const struct ath_hw_detect generic_hw_info = {
+ .vendor_name = "Unknown",
+ .card_name = "Generic",
+ .vendor = PCI_ANY_ID,
+ .id = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subid = PCI_ANY_ID
+};
+
static const char *hal_status_desc[] = {
"No error",
"No hardware present or device not yet supported",
@@ -542,6 +552,8 @@ ath_attach(u_int16_t devid, struct net_d
DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
#endif
+ sc->sc_hwinfo = &generic_hw_info;
+
/* Allocate space for dynamically determined maximum VAP count */
sc->sc_bslot =
kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
@@ -1508,6 +1520,29 @@ ath_vap_create(struct ieee80211com *ic,
return vap;
}
+void
+ath_hw_detect(struct ath_softc *sc, const struct ath_hw_detect *cards, int n_cards, u32 vendor, u32 id, u32 subvendor, u32 subid)
+{
+ int i;
+
+ for (i = 0; i < n_cards; i++) {
+ const struct ath_hw_detect *c = &cards[i];
+
+ if ((c->vendor != PCI_ANY_ID) && c->vendor != vendor)
+ continue;
+ if ((c->id != PCI_ANY_ID) && c->id != id)
+ continue;
+ if ((c->subvendor != PCI_ANY_ID) && c->subvendor != subvendor)
+ continue;
+ if ((c->subid != PCI_ANY_ID) && c->subid != subid)
+ continue;
+
+ sc->sc_hwinfo = c;
+ sc->sc_poweroffset = c->poweroffset;
+ break;
+ }
+}
+
static void
ath_vap_delete(struct ieee80211vap *vap)
{
@@ -10225,6 +10260,7 @@ static u_int32_t
ath_set_clamped_maxtxpower(struct ath_softc *sc,
u_int32_t new_clamped_maxtxpower)
{
+ new_clamped_maxtxpower -= sc->sc_poweroffset;
(void)ath_hal_settxpowlimit(sc->sc_ah, new_clamped_maxtxpower);
return ath_get_clamped_maxtxpower(sc);
}
@@ -10238,6 +10274,7 @@ ath_get_clamped_maxtxpower(struct ath_so
{
u_int32_t clamped_maxtxpower;
(void)ath_hal_getmaxtxpow(sc->sc_ah, &clamped_maxtxpower);
+ clamped_maxtxpower += sc->sc_poweroffset;
return clamped_maxtxpower;
}
@@ -10821,6 +10858,12 @@ ath_ioctl(struct net_device *dev, struct
* is to add module parameters.
*/
+/* sysctls for hardware info */
+enum {
+ ATH_CARD_VENDOR,
+ ATH_CARD_NAME,
+};
+
/*
* Dynamic (i.e. per-device) sysctls. These are automatically
* mirrored in /proc/sys.
@@ -10900,6 +10943,38 @@ ath_sysctl_get_intmit(struct ath_softc *
}
static int
+ATH_SYSCTL_DECL(ath_sysctl_hwinfo, ctl, write, filp, buffer, lenp, ppos)
+{
+ struct ath_softc *sc = ctl->extra1;
+ struct ath_hal *ah = sc->sc_ah;
+ int ret = 0;
+
+ if (write)
+ return -EINVAL;
+
+ ATH_LOCK(sc);
+ switch((long)ctl->extra2) {
+ case ATH_CARD_VENDOR:
+ ctl->data = (char *)sc->sc_hwinfo->vendor_name;
+ break;
+ case ATH_CARD_NAME:
+ ctl->data = (char *)sc->sc_hwinfo->card_name;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret == 0) {
+ ctl->maxlen = strlen(ctl->data);
+ ret = ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp,
+ buffer, lenp, ppos);
+ }
+ ATH_UNLOCK(sc);
+
+ return ret;
+}
+
+static int
ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
{
struct ath_softc *sc = ctl->extra1;
@@ -11179,6 +11254,24 @@ static int maxint = 0x7fffffff; /* 32-b
static const ctl_table ath_sysctl_template[] = {
{ .ctl_name = CTL_AUTO,
+ .procname = "dev_vendor",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_hwinfo,
+ .strategy = &sysctl_string,
+ .data = "N/A",
+ .maxlen = 1,
+ .extra2 = (void *)ATH_CARD_VENDOR,
+ },
+ { .ctl_name = CTL_AUTO,
+ .procname = "dev_name",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_hwinfo,
+ .strategy = &sysctl_string,
+ .data = "N/A",
+ .maxlen = 1,
+ .extra2 = (void *)ATH_CARD_NAME,
+ },
+ { .ctl_name = CTL_AUTO,
.procname = "slottime",
.mode = 0644,
.proc_handler = ath_sysctl_halparam,
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -168,12 +168,16 @@ static inline struct net_device *_alloc_
void __user *buffer, size_t *lenp)
#define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
proc_dointvec(ctl, write, filp, buffer, lenp)
+#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
+ proc_dostring(ctl, write, filp, buffer, lenp)
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) */
#define ATH_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \
f(ctl_table *ctl, int write, struct file *filp, \
void __user *buffer, size_t *lenp, loff_t *ppos)
#define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
proc_dointvec(ctl, write, filp, buffer, lenp, ppos)
+#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
+ proc_dostring(ctl, write, filp, buffer, lenp, ppos)
#endif
#define ATH_TIMEOUT 1000
@@ -469,6 +473,7 @@ struct ath_hal;
struct ath_desc;
struct ath_ratectrl;
struct ath_tx99;
+struct ath_hw_detect;
struct proc_dir_entry;
/*
@@ -629,6 +634,7 @@ struct ath_softc {
struct ath_ratectrl *sc_rc; /* tx rate control support */
struct ath_tx99 *sc_tx99; /* tx99 support */
void (*sc_setdefantenna)(struct ath_softc *, u_int);
+ const struct ath_hw_detect *sc_hwinfo;
unsigned int sc_invalid:1; /* being detached */
unsigned int sc_mrretry:1; /* multi-rate retry support */
@@ -683,6 +689,7 @@ struct ath_softc {
const HAL_RATE_TABLE *sc_quarter_rates; /* quarter rate table */
HAL_OPMODE sc_opmode; /* current hal operating mode */
enum ieee80211_phymode sc_curmode; /* current phy mode */
+ u_int sc_poweroffset; /* hardware power offset */
u_int16_t sc_curtxpow; /* current tx power limit */
u_int16_t sc_curaid; /* current association id */
HAL_CHANNEL sc_curchan; /* current h/w channel */
@@ -929,4 +936,16 @@ int ar_device(int devid);
void ath_radar_detected(struct ath_softc *sc, const char* message);
+struct ath_hw_detect {
+ const char *vendor_name;
+ const char *card_name;
+ u32 vendor;
+ u32 id;
+ u32 subvendor;
+ u32 subid;
+ u32 poweroffset;
+};
+
+extern void ath_hw_detect(struct ath_softc *sc, const struct ath_hw_detect *cards, int n_cards, u32 vendor, u32 id, u32 subvendor, u32 subid);
+
#endif /* _DEV_ATH_ATHVAR_H */
--- a/ath/if_ath_ahb.c
+++ b/ath/if_ath_ahb.c
@@ -20,6 +20,7 @@
#include <linux/netdevice.h>
#include <linux/cache.h>
#include <linux/platform_device.h>
+#include <linux/pci.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -181,12 +182,32 @@ exit_ath_wmac(u_int16_t wlanNum, struct
return 0;
}
+static const char ubnt[] = "Ubiquiti Networks";
+/* { vendorname, cardname, vendorid, cardid, subsys vendorid, subsys id, poweroffset } */
+static const struct ath_hw_detect cards[] = {
+ { ubnt, "PowerStation2 (18V)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb102 },
+ { ubnt, "PowerStation2 (16D)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb202 },
+ { ubnt, "PowerStation2 (EXT)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb302 },
+ { ubnt, "PowerStation5 (22V)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb105 },
+ { ubnt, "PowerStation5 (EXT)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb305 },
+ { ubnt, "WispStation5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xa105 },
+ { ubnt, "LiteStation2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xa002 },
+ { ubnt, "LiteStation5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xa005 },
+ { ubnt, "NanoStation2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc002 },
+ { ubnt, "NanoStation5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc005 },
+ { ubnt, "NanoStation Loco2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc102 },
+ { ubnt, "NanoStation Loco5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc105 },
+ { ubnt, "Bullet2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc202 },
+ { ubnt, "Bullet5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc205 },
+};
+
static int
init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
{
const char *athname;
struct net_device *dev;
struct ath_ahb_softc *sc;
+ u16 *radio_data;
if (((wlanNum != 0) && (wlanNum != 1)) ||
(sclist[wlanNum] != NULL))
@@ -248,6 +269,16 @@ init_ath_wmac(u_int16_t devid, u_int16_t
sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
sc->aps_sc.sc_invalid = 0;
+ radio_data = (u16 *) config->radio;
+ if (radio_data) {
+ u16 vendor, id, subvendor, subid;
+ vendor = radio_data[1];
+ id = radio_data[0];
+ subvendor = radio_data[8];
+ subid = radio_data[7];
+ ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);
+ }
+
return 0;
bad4:
--- a/ath/if_ath_pci.c
+++ b/ath/if_ath_pci.c
@@ -123,6 +123,33 @@ static u16 ath_devidmap[][2] = {
{ 0xff1a, 0x001a }
};
+static const char ubnt[] = "Ubiquiti Networks";
+/* { vendorname, cardname, vendorid, cardid, subsys vendorid, subsys id, poweroffset } */
+static const struct ath_hw_detect cards[] = {
+ { ubnt, "XR2", 0x168c, 0x001b, 0x0777, 0x3002, 10 },
+ { ubnt, "XR2", 0x168c, 0x001b, 0x7777, 0x3002, 10 },
+ { ubnt, "XR2.3", 0x168c, 0x001b, 0x0777, 0x3b02, 10 },
+ { ubnt, "XR2.6", 0x168c, 0x001b, 0x0777, 0x3c02, 10 },
+ { ubnt, "XR3-2.8", 0x168c, 0x001b, 0x0777, 0x3b03, 10 },
+ { ubnt, "XR3-3.6", 0x168c, 0x001b, 0x0777, 0x3c03, 10 },
+ { ubnt, "XR3", 0x168c, 0x001b, 0x0777, 0x3003, 10 },
+ { ubnt, "XR4", 0x168c, 0x001b, 0x0777, 0x3004, 10 },
+ { ubnt, "XR5", 0x168c, 0x001b, 0x0777, 0x3005, 10 },
+ { ubnt, "XR5", 0x168c, 0x001b, 0x7777, 0x3005, 10 },
+ { ubnt, "XR7", 0x168c, 0x001b, 0x0777, 0x3007, 10 },
+ { ubnt, "XR9", 0x168c, 0x001b, 0x0777, 0x3009, 10 },
+ { ubnt, "SRC", 0x168c, 0x0013, 0x168c, 0x1042, 1 },
+ { ubnt, "SR2", 0x168c, 0x0013, 0x0777, 0x2041, 10 },
+ { ubnt, "SR4", 0x168c, 0x0013, 0x0777, 0x2004, 6 },
+ { ubnt, "SR4", 0x168c, 0x0013, 0x7777, 0x2004, 6 },
+ { ubnt, "SR4C", 0x168c, 0x0013, 0x0777, 0x1004, 6 },
+ { ubnt, "SR4C", 0x168c, 0x0013, 0x7777, 0x1004, 6 },
+ { ubnt, "SR5", 0x168c, 0x0013, 0x168c, 0x2042, 7 },
+ { ubnt, "SR9", 0x168c, 0x0013, 0x7777, 0x2009, 12 },
+ { ubnt, "SR71A", 0x168c, 0x0027, 0x168c, 0x2082, 10 },
+ { ubnt, "SR71", 0x168c, 0x0027, 0x0777, 0x4082, 10 },
+};
+
static int
ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -257,6 +284,10 @@ ath_pci_probe(struct pci_dev *pdev, cons
printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
dev_info, dev->name, athname ? athname : "Atheros ???", phymem, dev->irq);
+ ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards),
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device);
+
/* ready to process interrupts */
sc->aps_sc.sc_invalid = 0;

View File

@ -0,0 +1,10 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6669,6 +6669,7 @@ ath_setdefantenna(struct ath_softc *sc,
struct ath_hal *ah = sc->sc_ah;
/* XXX block beacon interrupts */
+ ath_hal_setdiversity(ah, (sc->sc_diversity != 0));
ath_hal_setdefantenna(ah, antenna);
if (sc->sc_defant != antenna)
sc->sc_stats.ast_ant_defswitch++;

View File

@ -0,0 +1,116 @@
fixes ACL race condition caused by acl list modifications at run time
Signed-off-by: Sebastian Gottschall <brainslayer@dd-wrt.com>
--- a/net80211/ieee80211_acl.c
+++ b/net80211/ieee80211_acl.c
@@ -112,9 +112,9 @@ acl_detach(struct ieee80211vap *vap)
{
struct aclstate *as = vap->iv_as;
- ACL_LOCK(as);
+ ACL_LOCK_IRQ(as);
acl_free_all_locked(as);
- ACL_UNLOCK(as);
+ ACL_UNLOCK_IRQ(as);
vap->iv_as = NULL;
ACL_LOCK_DESTROY(as);
FREE(as, M_DEVBUF);
@@ -128,11 +128,18 @@ _find_acl(struct aclstate *as, const u_i
struct acl *acl;
int hash;
+ /* locking needed, as inserts are not atomic */
+ ACL_LOCK_IRQ(as);
hash = ACL_HASH(macaddr);
LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
- if (IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
- return acl;
+ if (!IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
+ continue;
+
+ ACL_UNLOCK_IRQ_EARLY(as);
+ return acl;
}
+ ACL_UNLOCK_IRQ(as);
+
return NULL;
}
@@ -176,11 +183,11 @@ acl_add(struct ieee80211vap *vap, const
return -ENOMEM;
}
- ACL_LOCK(as);
+ ACL_LOCK_IRQ(as);
hash = ACL_HASH(mac);
LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
if (IEEE80211_ADDR_EQ(acl->acl_macaddr, mac)) {
- ACL_UNLOCK_EARLY(as);
+ ACL_UNLOCK_IRQ_EARLY(as);
FREE(new, M_80211_ACL);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: add " MAC_FMT " failed, already present\n",
@@ -191,7 +198,7 @@ acl_add(struct ieee80211vap *vap, const
IEEE80211_ADDR_COPY(new->acl_macaddr, mac);
TAILQ_INSERT_TAIL(&as->as_list, new, acl_list);
LIST_INSERT_HEAD(&as->as_hash[hash], new, acl_hash);
- ACL_UNLOCK(as);
+ ACL_UNLOCK_IRQ(as);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: add " MAC_FMT "\n", MAC_ADDR(mac));
@@ -204,11 +211,11 @@ acl_remove(struct ieee80211vap *vap, con
struct aclstate *as = vap->iv_as;
struct acl *acl;
- ACL_LOCK(as);
+ ACL_LOCK_IRQ(as);
acl = _find_acl(as, mac);
if (acl != NULL)
_acl_free(as, acl);
- ACL_UNLOCK(as);
+ ACL_UNLOCK_IRQ(as);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: remove " MAC_FMT "%s\n", MAC_ADDR(mac),
@@ -235,9 +242,9 @@ acl_free_all(struct ieee80211vap *vap)
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL, "ACL: %s\n", "free all");
- ACL_LOCK(as);
+ ACL_LOCK_IRQ(as);
acl_free_all_locked(vap->iv_as);
- ACL_UNLOCK(as);
+ ACL_UNLOCK_IRQ(as);
return 0;
}
--- a/net80211/ieee80211_linux.h
+++ b/net80211/ieee80211_linux.h
@@ -319,16 +319,15 @@ typedef spinlock_t ieee80211_scan_lock_t
typedef spinlock_t acl_lock_t;
#define ACL_LOCK_INIT(_as, _name) spin_lock_init(&(_as)->as_lock)
#define ACL_LOCK_DESTROY(_as)
-#define ACL_LOCK(_as) do { \
- ACL_LOCK_CHECK(_as); \
- spin_lock(&(_as)->as_lock);
-#define ACL_UNLOCK(_as) \
- ACL_LOCK_ASSERT(_as); \
- spin_unlock(&(_as)->as_lock); \
-} while(0)
-#define ACL_UNLOCK_EARLY(_as) \
- ACL_LOCK_ASSERT(_as); \
- spin_unlock(&(_as)->as_lock);
+#define ACL_LOCK_IRQ(_as) do { \
+ unsigned long __acl_lockflags; \
+ spin_lock_irqsave(&(_as)->as_lock, __acl_lockflags);
+#define ACL_UNLOCK_IRQ(_as) \
+ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
+} while (0)
+#define ACL_UNLOCK_IRQ_EARLY(_as) do { \
+ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
+} while (0)
#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
#define ACL_LOCK_ASSERT(_as) \

View File

@ -0,0 +1,85 @@
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -198,6 +198,7 @@ struct ieee80211vap {
u_int32_t iv_debug; /* debug msg flags */
struct ieee80211_stats iv_stats; /* statistics */
+ int iv_max_nodes;
int iv_monitor_nods_only; /* in monitor mode only nods traffic */
int iv_monitor_txf_len; /* in monitor mode, truncate tx packets */
int iv_monitor_phy_errors; /* in monitor mode, accept phy errors */
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -650,6 +650,7 @@ enum {
IEEE80211_PARAM_RSSI_DIS_THR = 80, /* rssi threshold for disconnection */
IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */
+ IEEE80211_PARAM_MAXASSOC = 83, /* maximum associated stations */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2875,6 +2875,12 @@ ieee80211_ioctl_setparam(struct net_devi
else
vap->iv_flags_ext &= ~IEEE80211_FEXT_WDSSEP;
break;
+ case IEEE80211_PARAM_MAXASSOC:
+ if (vap->iv_opmode != IEEE80211_M_HOSTAP)
+ retv = -EINVAL;
+ else
+ vap->iv_max_nodes = value;
+ break;
#ifdef ATH_REVERSE_ENGINEERING
case IEEE80211_PARAM_DUMPREGS:
ieee80211_dump_registers(dev, info, w, extra);
@@ -3234,6 +3240,9 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_WDS_SEP:
param[0] = !!(vap->iv_flags_ext & IEEE80211_FEXT_WDSSEP);
break;
+ case IEEE80211_PARAM_MAXASSOC:
+ param[0] = vap->iv_max_nodes;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -5789,6 +5798,10 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wdssep"},
{ IEEE80211_PARAM_WDS_SEP,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_wdssep"},
+ { IEEE80211_PARAM_MAXASSOC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxassoc"},
+ { IEEE80211_PARAM_MAXASSOC,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxassoc"},
#ifdef ATH_REVERSE_ENGINEERING
/*
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -4020,7 +4020,26 @@ ieee80211_recv_mgmt(struct ieee80211vap
vap->iv_stats.is_rx_assoc_norate++;
return;
}
+ if (vap->iv_max_nodes > 0) {
+ unsigned int active_nodes = 0;
+ struct ieee80211_node *tni;
+ IEEE80211_NODE_TABLE_LOCK_IRQ(&ic->ic_sta);
+ TAILQ_FOREACH(tni, &ic->ic_sta.nt_node, ni_list) {
+ if (tni->ni_vap != vap)
+ continue;
+ if (tni->ni_associd == 0)
+ continue;
+ active_nodes++;
+ }
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(&ic->ic_sta);
+
+ if (active_nodes >= vap->iv_max_nodes) {
+ /* too many nodes connected */
+ ieee80211_node_leave(ni);
+ return;
+ }
+ }
if (ni->ni_associd != 0 &&
IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) {
if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)

View File

@ -0,0 +1,60 @@
--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
@@ -1415,7 +1415,8 @@ __ieee80211_newstate(struct ieee80211vap
vap->iv_state = nstate; /* state transition */
del_timer(&vap->iv_mgtsend);
if ((vap->iv_opmode != IEEE80211_M_HOSTAP) &&
- (ostate != IEEE80211_S_SCAN))
+ (ostate != IEEE80211_S_SCAN) &&
+ !(vap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING))
ieee80211_cancel_scan(vap); /* background scan */
ni = vap->iv_bss; /* NB: no reference held */
switch (nstate) {
@@ -1457,7 +1458,8 @@ __ieee80211_newstate(struct ieee80211vap
}
goto reset;
case IEEE80211_S_SCAN:
- ieee80211_cancel_scan(vap);
+ if (!(vap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING))
+ ieee80211_cancel_scan(vap);
goto reset;
reset:
ieee80211_reset_bss(vap);
@@ -1995,7 +1997,9 @@ ieee80211_newstate(struct ieee80211vap *
}
}
}
- } else if (dstate == IEEE80211_S_SCAN) {
+ } else if ((dstate == IEEE80211_S_SCAN) ||
+ (dstate == IEEE80211_S_AUTH) ||
+ (dstate == IEEE80211_S_ASSOC)) {
/* Force to scan pending... someone is scanning */
vap->iv_flags_ext |= IEEE80211_FEXT_SCAN_PENDING;
__ieee80211_newstate(vap, IEEE80211_S_INIT, arg);
--- a/net80211/ieee80211_output.c
+++ b/net80211/ieee80211_output.c
@@ -238,7 +238,9 @@ ieee80211_hardstart(struct sk_buff *skb,
}
/* Cancel any running BG scan */
- if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && (vap->iv_state == IEEE80211_S_RUN))
+ if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) &&
+ (vap->iv_state == IEEE80211_S_RUN) &&
+ (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN))
ieee80211_cancel_scan(vap);
/*
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2728,9 +2728,9 @@ ieee80211_ioctl_setparam(struct net_devi
return -EINVAL;
vap->iv_flags |= IEEE80211_F_BGSCAN;
} else {
- /* XXX racey? */
+ if (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)
+ ieee80211_cancel_scan(vap); /* anything current */
vap->iv_flags &= ~IEEE80211_F_BGSCAN;
- ieee80211_cancel_scan(vap); /* anything current */
}
break;
case IEEE80211_PARAM_BGSCAN_IDLE:

View File

@ -0,0 +1,249 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -384,6 +384,7 @@ static u_int32_t ath_get_real_maxtxpower
static void ath_poll_disable(struct net_device *dev);
static void ath_poll_enable(struct net_device *dev);
+static void ath_fetch_idle_time(struct ath_softc *sc);
/* calibrate every 30 secs in steady state but check every second at first. */
static int ath_calinterval = ATH_SHORT_CALINTERVAL;
@@ -2581,6 +2582,7 @@ ath_init(struct net_device *dev)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
+ ath_fetch_idle_time(sc);
sc->sc_curchan.channel = ic->ic_curchan->ic_freq;
sc->sc_curchan.channelFlags = ath_chan2flags(ic->ic_curchan);
if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan, AH_FALSE, &status)) {
@@ -2914,6 +2916,48 @@ ath_hw_check_atim(struct ath_softc *sc,
return 0;
}
+#define AR5K_MIBC 0x0040
+#define AR5K_MIBC_FREEZE (1 << 1)
+#define AR5K_TXFC 0x80ec
+#define AR5K_RXFC 0x80f0
+#define AR5K_RXCLEAR 0x80f4
+#define AR5K_CYCLES 0x80f8
+static void
+ath_fetch_idle_time(struct ath_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t cc, rx;
+ u_int32_t time = 0;
+
+ if (sc->sc_ah->ah_macType < 5212)
+ return;
+
+ if (!ic->ic_curchan || (ic->ic_curchan == IEEE80211_CHAN_ANYC))
+ return;
+
+ OS_REG_WRITE(ah, AR5K_MIBC, AR5K_MIBC_FREEZE);
+ rx = OS_REG_READ(ah, AR5K_RXCLEAR);
+ cc = OS_REG_READ(ah, AR5K_CYCLES);
+
+ if (!cc)
+ return;
+
+ if (rx > cc)
+ return; /* should not happen */
+
+ if (sc->sc_last_chan)
+ sc->sc_last_chan->ic_idletime = 100 * (cc - rx) / cc;
+ sc->sc_last_chan = ic->ic_curchan;
+
+ OS_REG_WRITE(ah, AR5K_RXCLEAR, 0);
+ OS_REG_WRITE(ah, AR5K_CYCLES, 0);
+ OS_REG_WRITE(ah, AR5K_TXFC, 0);
+ OS_REG_WRITE(ah, AR5K_RXFC, 0);
+ OS_REG_WRITE(ah, AR5K_MIBC, 0);
+}
+#undef AR5K_RXCLEAR
+#undef AR5K_CYCLES
/*
* Reset the hardware w/o losing operational state. This is
@@ -2941,6 +2985,7 @@ ath_reset(struct net_device *dev)
* Convert to a HAL channel description with the flags
* constrained to reflect the current operating mode.
*/
+ ath_fetch_idle_time(sc);
c = ic->ic_curchan;
sc->sc_curchan.channel = c->ic_freq;
sc->sc_curchan.channelFlags = ath_chan2flags(c);
@@ -9023,6 +9068,7 @@ ath_chan_set(struct ath_softc *sc, struc
u_int8_t channel_change_required = 0;
struct timeval tv;
+
/*
* Convert to a HAL channel description with
* the flags constrained to reflect the current
@@ -9031,6 +9077,14 @@ ath_chan_set(struct ath_softc *sc, struc
memset(&hchan, 0, sizeof(HAL_CHANNEL));
hchan.channel = chan->ic_freq;
hchan.channelFlags = ath_chan2flags(chan);
+
+ /* don't do duplicate channel changes, but do
+ * store the available idle time */
+ ath_fetch_idle_time(sc);
+ if ((sc->sc_curchan.channel == hchan.channel) &&
+ (sc->sc_curchan.channelFlags == hchan.channelFlags))
+ return 0;
+
KASSERT(hchan.channel != 0,
("bogus channel %u/0x%x", hchan.channel, hchan.channelFlags));
do_gettimeofday(&tv);
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -774,6 +774,7 @@ struct ath_softc {
struct ieee80211vap **sc_bslot; /* beacon xmit slots */
int sc_bnext; /* next slot for beacon xmit */
+ struct ieee80211_channel *sc_last_chan;
int sc_beacon_cal; /* use beacon timer for calibration */
u_int64_t sc_lastcal; /* last time the calibration was performed */
struct timer_list sc_cal_ch; /* calibration timer */
--- a/net80211/_ieee80211.h
+++ b/net80211/_ieee80211.h
@@ -148,6 +148,7 @@ struct ieee80211_channel {
int8_t ic_maxpower; /* maximum tx power in dBm */
int8_t ic_minpower; /* minimum tx power in dBm */
u_int8_t ic_scanflags;
+ u_int8_t ic_idletime; /* phy idle time in % */
};
#define IEEE80211_CHAN_MAX 255
--- a/net80211/ieee80211_scan_ap.c
+++ b/net80211/ieee80211_scan_ap.c
@@ -417,6 +417,19 @@ pc_cmp_rssi(struct ap_state *as, struct
/* This function must be invoked with locks acquired */
static int
+pc_cmp_idletime(struct ieee80211_channel *a,
+ struct ieee80211_channel *b)
+{
+ if (!a->ic_idletime || !b->ic_idletime)
+ return 0;
+
+ /* a is better than b (return < 0) when a has more idle time than b */
+ return b->ic_idletime - a->ic_idletime;
+}
+
+
+/* This function must be invoked with locks acquired */
+static int
pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a,
struct ieee80211_channel *b)
{
@@ -451,6 +464,7 @@ pc_cmp(const void *_a, const void *_b)
EVALUATE_CRITERION(radar, a, b);
EVALUATE_CRITERION(keepmode, params, a, b);
+ EVALUATE_CRITERION(idletime, a, b);
EVALUATE_CRITERION(sc, ic, a, b);
/* XXX: rssi useless? pick_channel evaluates it anyway */
EVALUATE_CRITERION(rssi, params->ss->ss_priv, a, b);
@@ -519,16 +533,9 @@ pick_channel(struct ieee80211_scan_state
#endif
best = NULL;
- best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */
for (i = 0; i < ss_last; i++) {
c = &chans[i];
- benefit = best_rssi - as->as_maxrssi[c->chan->ic_ieee];
- sta_assoc = ic->ic_sta_assoc;
-
- /* Don't switch... */
- if (benefit <= 0)
- continue;
/* Verify channel is not marked for non-occupancy */
if (IEEE80211_IS_CHAN_RADAR(c->chan))
@@ -546,31 +553,8 @@ pick_channel(struct ieee80211_scan_state
break;
}
- if (sta_assoc != 0) {
- int sl = ic->ic_cn_total -
- ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */
- if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) {
- int sl_max = ic->ic_sc_sldg * benefit;
- sl = 1000 * sl / sta_assoc; /* permil */
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: chan %d, dB gained: %d, "
- "STAs lost: %d permil (max %d)\n",
- __func__, c->chan->ic_ieee,
- benefit, sl, sl_max);
- if (sl > sl_max)
- continue;
- } else if (((ic->ic_sc_algorithm ==
- IEEE80211_SC_TIGHT) ||
- (ic->ic_sc_algorithm ==
- IEEE80211_SC_STRICT)) &&
- (sl > 0)) {
- /* Break the loop as the subsequent chans
- * won't be better. */
- break;
- }
- }
best = c->chan;
- best_rssi = as->as_maxrssi[best->ic_ieee];
+ break;
}
if (best != NULL) {
@@ -599,6 +583,9 @@ ap_end(struct ieee80211_scan_state *ss,
("wrong opmode %u", vap->iv_opmode));
ic = vap->iv_ic;
+
+ /* record stats for the channel that was scanned last */
+ ic->ic_set_channel(ic);
bestchan = pick_channel(ss, vap, flags);
if (bestchan == NULL) {
if (ss->ss_last > 0) {
--- a/net80211/ieee80211_scan.c
+++ b/net80211/ieee80211_scan.c
@@ -1002,20 +1002,34 @@ ieee80211_scan_add_channels(struct ieee8
{
struct ieee80211_channel *c, *cg;
u_int modeflags;
+ int has_non_turbo = 0;
int i;
KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
modeflags = chanflags[mode];
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
+ if (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO))
+ continue;
+
+ has_non_turbo = 1;
+ break;
+ }
+ for (i = 0; i < ic->ic_nchans; i++) {
+ c = &ic->ic_channels[i];
if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
continue;
if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
continue;
- if (modeflags &&
- ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
- (modeflags & IEEE80211_CHAN_ALLTURBO)))
- continue;
+ if (modeflags) {
+ if ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
+ (modeflags & IEEE80211_CHAN_ALLTURBO))
+ continue;
+ } else if (has_non_turbo) {
+ if ((ss->ss_vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+ (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)))
+ continue;
+ }
if (mode == IEEE80211_MODE_AUTO) {
/*
* XXX special-case 11b/g channels so we select

View File

@ -0,0 +1,13 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -4443,7 +4443,9 @@ ath_eth_type_trans(struct sk_buff *skb,
if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
skb->pkt_type = PACKET_OTHERHOST;
- return eth->h_proto;
+ if ((ntohs(eth->h_proto) >= 1536) || (ntohs(eth->h_proto) < 38))
+ return eth->h_proto;
+ return htons(ETH_P_802_2);
}
#endif

View File

@ -0,0 +1,29 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -1375,7 +1375,7 @@ ieee80211_auth_open(struct ieee80211_nod
vap->iv_stats.is_rx_bad_auth++; /* XXX maybe a unique error? */
if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
if (ni == vap->iv_bss) {
- ni = ieee80211_dup_bss(vap, wh->i_addr2, 0);
+ ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
if (ni == NULL)
return;
tmpnode = 1;
@@ -1763,6 +1763,8 @@ ieee80211_ssid_mismatch(struct ieee80211
}
#define IEEE80211_VERIFY_SSID(_ni, _ssid) do { \
+ if ((_ni)->ni_esslen == 0) \
+ return; \
if ((_ssid)[1] != 0 && \
((_ssid)[1] != (_ni)->ni_esslen || \
memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \
@@ -1777,6 +1779,8 @@ ieee80211_ssid_mismatch(struct ieee80211
} while (0)
#else /* !IEEE80211_DEBUG */
#define IEEE80211_VERIFY_SSID(_ni, _ssid) do { \
+ if ((_ni)->ni_esslen == 0) \
+ return; \
if ((_ssid)[1] != 0 && \
((_ssid)[1] != (_ni)->ni_esslen || \
memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \

View File

@ -0,0 +1,388 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -568,36 +568,6 @@ ieee80211_input(struct ieee80211vap * va
}
}
- /* XXX: Useless node mgmt API; make better */
- if ((dir == IEEE80211_FC1_DIR_DSTODS) && !vap->iv_wdsnode &&
- !ni_wds && !ni->ni_subif) {
- struct ieee80211_node_table *nt = &ic->ic_sta;
- struct ieee80211_frame_addr4 *wh4;
-
- if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) {
- IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
- wh, "data", "%s", "4 addr not allowed");
- goto err;
- }
- wh4 = (struct ieee80211_frame_addr4 *)skb->data;
- ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4);
- /* Last call increments ref count if !NULL */
- if ((ni_wds != NULL) && (ni_wds != ni)) {
- /*
- * node with source address (addr4) moved
- * to another WDS capable station. remove the
- * reference to the previous station and add
- * reference to the new one
- */
- (void) ieee80211_remove_wds_addr(nt, wh4->i_addr4);
- ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0);
- }
- if (ni_wds == NULL)
- ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0);
- else
- ieee80211_unref_node(&ni_wds);
- }
-
/*
* Check for power save state change.
*/
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -122,7 +122,6 @@ static void ieee80211_node_table_init(st
static void ieee80211_node_table_cleanup(struct ieee80211_node_table *);
static void ieee80211_node_table_reset(struct ieee80211_node_table *,
struct ieee80211vap *);
-static void ieee80211_node_wds_ageout(unsigned long);
MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
@@ -785,10 +784,6 @@ ieee80211_node_table_init(struct ieee802
nt->nt_name = name;
nt->nt_scangen = 1;
nt->nt_inact_init = inact;
- init_timer(&nt->nt_wds_aging_timer);
- nt->nt_wds_aging_timer.function = ieee80211_node_wds_ageout;
- nt->nt_wds_aging_timer.data = (unsigned long) nt;
- mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);
}
static __inline
@@ -1204,142 +1199,6 @@ void ieee80211_wds_addif(struct ieee8021
schedule_work(&ni->ni_create);
}
-/* Add wds address to the node table */
-int
-#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_add_wds_addr_debug(struct ieee80211_node_table *nt,
- struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static,
- const char* func, int line)
-#else
-ieee80211_add_wds_addr(struct ieee80211_node_table *nt,
- struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static)
-#endif
-{
- int hash;
- struct ieee80211_wds_addr *wds;
-
- MALLOC(wds, struct ieee80211_wds_addr *, sizeof(struct ieee80211_wds_addr),
- M_80211_WDS, M_NOWAIT | M_ZERO);
- if (wds == NULL) {
- /* XXX msg */
- return 1;
- }
- if (wds_static)
- wds->wds_agingcount = WDS_AGING_STATIC;
- else
- wds->wds_agingcount = WDS_AGING_COUNT;
- hash = IEEE80211_NODE_HASH(macaddr);
- IEEE80211_ADDR_COPY(wds->wds_macaddr, macaddr);
-
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
-#ifdef IEEE80211_DEBUG_REFCNT
- wds->wds_ni = ieee80211_ref_node_debug(ni, func, line);
-#else
- wds->wds_ni = ieee80211_ref_node(ni);
-#endif
- LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash);
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
- return 0;
-}
-#ifdef IEEE80211_DEBUG_REFCNT
-EXPORT_SYMBOL(ieee80211_add_wds_addr_debug);
-#else
-EXPORT_SYMBOL(ieee80211_add_wds_addr);
-#endif
-
-/* remove wds address from the wds hash table */
-void
-#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_remove_wds_addr_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr,
- const char* func, int line)
-#else
-ieee80211_remove_wds_addr(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
-#endif
-{
- int hash;
- struct ieee80211_wds_addr *wds, *twds;
-
- hash = IEEE80211_NODE_HASH(macaddr);
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
- LIST_REMOVE(wds, wds_hash);
-#ifdef IEEE80211_DEBUG_REFCNT
- ieee80211_unref_node_debug(&wds->wds_ni, func, line);
-#else
- ieee80211_unref_node(&wds->wds_ni);
-#endif
- FREE(wds, M_80211_WDS);
- break;
- }
- }
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
-}
-#ifdef IEEE80211_DEBUG_REFCNT
-EXPORT_SYMBOL(ieee80211_remove_wds_addr_debug);
-#else
-EXPORT_SYMBOL(ieee80211_remove_wds_addr);
-#endif
-
-/* Remove node references from wds table */
-void
-#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_del_wds_node_debug(struct ieee80211_node_table *nt, struct ieee80211_node *ni,
- const char* func, int line)
-#else
-ieee80211_del_wds_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
-#endif
-{
- int hash;
- struct ieee80211_wds_addr *wds, *twds;
-
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
- for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
- if (wds->wds_ni == ni) {
- LIST_REMOVE(wds, wds_hash);
-#ifdef IEEE80211_DEBUG_REFCNT
- ieee80211_unref_node_debug(&wds->wds_ni, func, line);
-#else
- ieee80211_unref_node(&wds->wds_ni);
-#endif
- FREE(wds, M_80211_WDS);
- }
- }
- }
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
-}
-#ifdef IEEE80211_DEBUG_REFCNT
-EXPORT_SYMBOL(ieee80211_del_wds_node_debug);
-#else
-EXPORT_SYMBOL(ieee80211_del_wds_node);
-#endif
-
-static void
-ieee80211_node_wds_ageout(unsigned long data)
-{
- struct ieee80211_node_table *nt = (struct ieee80211_node_table *)data;
- int hash;
- struct ieee80211_wds_addr *wds, *twds;
-
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
- for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
- if (wds->wds_agingcount != WDS_AGING_STATIC) {
- if (!wds->wds_agingcount) {
- LIST_REMOVE(wds, wds_hash);
- ieee80211_unref_node(&wds->wds_ni);
- FREE(wds, M_80211_WDS);
- } else
- wds->wds_agingcount--;
- }
- }
- }
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
- mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);
-}
-
-
/* Add the specified station to the station table.
* Allocates a new ieee80211_node* that has a reference count of one
* If tmp is 0, it is added to the node table and the reference is used.
@@ -1385,34 +1244,6 @@ ieee80211_dup_bss(struct ieee80211vap *v
return ni;
}
-static struct ieee80211_node *
-#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_find_wds_node_locked_debug(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, const char* func, int line)
-#else
-ieee80211_find_wds_node_locked(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr)
-#endif
-{
- struct ieee80211_wds_addr *wds;
- int hash;
- IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
-
- hash = IEEE80211_NODE_HASH(macaddr);
- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
- if (wds->wds_agingcount != WDS_AGING_STATIC)
- wds->wds_agingcount = WDS_AGING_COUNT; /* reset the aging count */
-#ifdef IEEE80211_DEBUG_REFCNT
- return ieee80211_ref_node_debug(wds->wds_ni, func, line);
-#else
- return ieee80211_ref_node(wds->wds_ni);
-#endif
- }
- }
- return NULL;
-}
-
/* NB: A node reference is acquired here; the caller MUST release it. */
#ifdef IEEE80211_DEBUG_REFCNT
#define ieee80211_find_node_locked(nt, mac) \
@@ -1430,7 +1261,6 @@ ieee80211_find_node_locked(struct ieee80
{
struct ieee80211_node *ni;
int hash;
- struct ieee80211_wds_addr *wds;
IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
@@ -1445,48 +1275,11 @@ ieee80211_find_node_locked(struct ieee80
return ni;
}
}
-
- /* Now, we look for the desired mac address in the 4 address
- nodes. */
- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
-#ifdef IEEE80211_DEBUG_REFCNT
- return ieee80211_ref_node_debug(wds->wds_ni, func, line);
-#else
- return ieee80211_ref_node(wds->wds_ni);
-#endif
- }
- }
return NULL;
}
struct ieee80211_node *
#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_find_wds_node_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr,
- const char* func, int line)
-#else
-ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
-#endif
-{
- struct ieee80211_node *ni;
-
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
-#ifdef IEEE80211_DEBUG_REFCNT
- ni = ieee80211_find_wds_node_locked_debug(nt, macaddr, func, line);
-#else
- ni = ieee80211_find_wds_node_locked(nt, macaddr);
-#endif
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
- return ni;
-}
-#ifdef IEEE80211_DEBUG_REFCNT
-EXPORT_SYMBOL(ieee80211_find_wds_node_debug);
-#else
-EXPORT_SYMBOL(ieee80211_find_wds_node);
-#endif
-
-struct ieee80211_node *
-#ifdef IEEE80211_DEBUG_REFCNT
ieee80211_find_node_debug(struct ieee80211_node_table *nt,
const u_int8_t *macaddr, const char *func, int line)
#else
@@ -1838,7 +1631,6 @@ ieee80211_node_table_cleanup(struct ieee
ic->ic_node_cleanup(ni);
#endif
}
- del_timer(&nt->nt_wds_aging_timer);
IEEE80211_SCAN_LOCK_DESTROY(nt);
IEEE80211_NODE_TABLE_LOCK_DESTROY(nt);
}
@@ -2404,8 +2196,6 @@ ieee80211_node_leave(struct ieee80211_no
* so no more references are generated
*/
if (nt) {
- ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
- ieee80211_del_wds_node(nt, ni);
IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
node_table_leave_locked(nt, ni);
IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
--- a/net80211/ieee80211_node.h
+++ b/net80211/ieee80211_node.h
@@ -231,13 +231,6 @@ void ieee80211_sta_leave(struct ieee8021
#define WDS_AGING_STATIC 0xffff
#define WDS_AGING_TIMER_VAL (WDS_AGING_TIME / 2)
-struct ieee80211_wds_addr {
- LIST_ENTRY(ieee80211_wds_addr) wds_hash;
- u_int8_t wds_macaddr[IEEE80211_ADDR_LEN];
- struct ieee80211_node *wds_ni;
- u_int16_t wds_agingcount;
-};
-
/*
* Table of ieee80211_node instances. Each ieee80211com
* has at least one for holding the scan candidates.
@@ -250,11 +243,9 @@ struct ieee80211_node_table {
ieee80211_node_table_lock_t nt_nodelock; /* on node table */
TAILQ_HEAD(, ieee80211_node) nt_node; /* information of all nodes */
ATH_LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE];
- ATH_LIST_HEAD(, ieee80211_wds_addr) nt_wds_hash[IEEE80211_NODE_HASHSIZE];
ieee80211_scan_lock_t nt_scanlock; /* on nt_scangen */
u_int nt_scangen; /* gen# for timeout scan */
int nt_inact_init; /* initial node inact setting */
- struct timer_list nt_wds_aging_timer; /* timer to age out wds entries */
};
/* Allocates a new ieee80211_node* that has a reference count of one, and
@@ -363,47 +354,6 @@ void
ieee80211_unref_node(struct ieee80211_node **pni);
#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
-/* Increments reference count of ieee80211_node *ni */
-#ifdef IEEE80211_DEBUG_REFCNT
-#define ieee80211_add_wds_addr(_table, _node, _mac, _static) \
- ieee80211_add_wds_addr_debug(_table, _node, _mac, _static, __func__, __LINE__)
-int ieee80211_add_wds_addr_debug(struct ieee80211_node_table *, struct ieee80211_node *,
- const u_int8_t *, u_int8_t, const char* func, int line);
-#else
-int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *,
- const u_int8_t *, u_int8_t);
-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
-
-/* Decrements reference count of ieee80211_node *ni */
-#ifdef IEEE80211_DEBUG_REFCNT
-#define ieee80211_remove_wds_addr(_table, _mac) \
- ieee80211_remove_wds_addr_debug(_table, _mac, __func__, __LINE__)
-void ieee80211_remove_wds_addr_debug(struct ieee80211_node_table *, const u_int8_t *,
- const char* func, int line);
-#else
-void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *);
-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
-
-/* Decrements reference count of node, if found */
-#ifdef IEEE80211_DEBUG_REFCNT
-#define ieee80211_del_wds_node(_table, _node) \
- ieee80211_del_wds_node_debug(_table, _node, __func__, __LINE__)
-void ieee80211_del_wds_node_debug(struct ieee80211_node_table *, struct ieee80211_node *,
- const char* func, int line);
-#else
-void ieee80211_del_wds_node(struct ieee80211_node_table *, struct ieee80211_node *);
-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
-
-/* Increments reference count of node, if found */
-#ifdef IEEE80211_DEBUG_REFCNT
-#define ieee80211_find_wds_node(_table, _mac) \
- ieee80211_find_wds_node_debug(_table, _mac, __func__, __LINE__)
-struct ieee80211_node *ieee80211_find_wds_node_debug(struct ieee80211_node_table *,
- const u_int8_t *, const char* func, int line);
-#else
-struct ieee80211_node *ieee80211_find_wds_node(struct ieee80211_node_table *,
- const u_int8_t *);
-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
typedef void ieee80211_iter_func(void *, struct ieee80211_node *);
void ieee80211_iterate_nodes(struct ieee80211_node_table *,
ieee80211_iter_func *, void *);

View File

@ -0,0 +1,491 @@
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -123,6 +123,9 @@ static void ieee80211_node_table_cleanup
static void ieee80211_node_table_reset(struct ieee80211_node_table *,
struct ieee80211vap *);
+static struct ieee80211_node *
+lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, const u_int8_t *addr);
+
MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
void
@@ -697,7 +700,7 @@ ieee80211_sta_join(struct ieee80211vap *
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni;
- ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);
+ ni = lookup_rxnode(ic, vap, se->se_macaddr);
if (ni == NULL) {
ni = ieee80211_alloc_node_table(vap, se->se_macaddr);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
@@ -1394,6 +1397,53 @@ ieee80211_add_neighbor(struct ieee80211v
return ni;
}
+struct ieee80211vap *
+ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac)
+{
+ struct ieee80211vap *vap;
+
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, mac))
+ return vap;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(ieee80211_find_rxvap);
+
+static struct ieee80211_node *
+lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
+ const u_int8_t *addr)
+{
+ struct ieee80211_node_table *nt;
+ struct ieee80211_node *ni = NULL;
+ int use_bss = 0;
+ int hash;
+
+ nt = &ic->ic_sta;
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+ hash = IEEE80211_NODE_HASH(addr);
+ LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
+ if (IEEE80211_ADDR_EQ(ni->ni_macaddr, addr)) {
+ /* allow multiple nodes on different vaps */
+ if (vap && (ni->ni_vap != vap))
+ continue;
+
+ ieee80211_ref_node(ni);
+ goto out;
+ }
+ }
+
+ /* no match found */
+ ni = NULL;
+
+out:
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+ return ni;
+#undef IS_PSPOLL
+#undef IS_CTL
+}
+
+
/*
* Return the node for the sender of a frame; if the sender is unknown return
* NULL. The caller is expected to deal with this. (The frame is sent to all
@@ -1403,10 +1453,10 @@ ieee80211_add_neighbor(struct ieee80211v
*/
struct ieee80211_node *
#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_find_rxnode_debug(struct ieee80211com *ic,
+ieee80211_find_rxnode_debug(struct ieee80211com *ic, struct ieee80211vap *vap,
const struct ieee80211_frame_min *wh, const char *func, int line)
#else
-ieee80211_find_rxnode(struct ieee80211com *ic,
+ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
const struct ieee80211_frame_min *wh)
#endif
{
@@ -1414,9 +1464,8 @@ ieee80211_find_rxnode(struct ieee80211co
((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
#define IS_PSPOLL(wh) \
((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
- struct ieee80211_node_table *nt;
- struct ieee80211_node *ni;
- struct ieee80211vap *vap, *avp;
+ struct ieee80211_node *ni = NULL;
+ struct ieee80211vap *avp;
const u_int8_t *addr;
if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
@@ -1429,32 +1478,25 @@ ieee80211_find_rxnode(struct ieee80211co
/* XXX check ic_bss first in station mode */
/* XXX 4-address frames? */
- nt = &ic->ic_sta;
- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) {
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ if (vap) { /* assume unicast if vap is set, mcast not supported for wds */
TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
- if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac))
+ if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac) ||
+ !IEEE80211_ADDR_EQ(wh->i_addr1, avp->iv_myaddr))
continue;
if (avp->iv_wdsnode)
- return ieee80211_ref_node(avp->iv_wdsnode);
- else
- return NULL;
+ ni = ieee80211_ref_node(avp->iv_wdsnode);
+ return ni;
}
+ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS))
+ return NULL;
+ } else {
+ return NULL;
}
}
-#ifdef IEEE80211_DEBUG_REFCNT
- ni = ieee80211_find_node_locked_debug(nt, addr, func, line);
-#else
- ni = ieee80211_find_node_locked(nt, addr);
-#endif
- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
-
- return ni;
-#undef IS_PSPOLL
-#undef IS_CTL
+ return lookup_rxnode(ic, vap, addr);
}
#ifdef IEEE80211_DEBUG_REFCNT
EXPORT_SYMBOL(ieee80211_find_rxnode_debug);
@@ -1479,15 +1521,14 @@ ieee80211_find_txnode(struct ieee80211va
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node_table *nt;
struct ieee80211_node *ni = NULL;
+ int hash;
- IEEE80211_LOCK_IRQ(ic);
if (vap->iv_opmode == IEEE80211_M_WDS) {
if (vap->iv_wdsnode && (vap->iv_state == IEEE80211_S_RUN))
return ieee80211_ref_node(vap->iv_wdsnode);
else
return NULL;
}
- IEEE80211_UNLOCK_IRQ(ic);
/*
* The destination address should be in the node table
@@ -1505,11 +1546,22 @@ ieee80211_find_txnode(struct ieee80211va
/* XXX: Can't hold lock across dup_bss due to recursive locking. */
nt = &vap->iv_ic->ic_sta;
IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+ hash = IEEE80211_NODE_HASH(mac);
+ LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
+ if (ni->ni_vap != vap)
+ continue;
+
+ if (IEEE80211_ADDR_EQ(ni->ni_macaddr, mac)) {
#ifdef IEEE80211_DEBUG_REFCNT
- ni = ieee80211_find_node_locked_debug(nt, mac, func, line);
+ ieee80211_ref_node_debug(ni, func, line);
#else
- ni = ieee80211_find_node_locked(nt, mac);
+ ieee80211_ref_node(ni);
#endif
+ goto found;
+ }
+ }
+ ni = NULL;
+found:
IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
if (ni == NULL) {
@@ -1964,13 +2016,32 @@ remove_worse_nodes(void *arg, struct iee
}
}
+static void
+remove_duplicate_nodes(void *arg, struct ieee80211_node *ni)
+{
+ struct ieee80211_node *rni = arg;
+
+ if (ni == rni)
+ return;
+
+ if (ni->ni_vap == rni->ni_vap)
+ return;
+
+ if (!IEEE80211_ADDR_EQ(rni->ni_macaddr, ni->ni_macaddr))
+ return;
+
+ ieee80211_node_leave(ni);
+}
+
void
ieee80211_node_join(struct ieee80211_node *ni, int resp)
{
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211_node *tni;
int newassoc;
+ ieee80211_iterate_nodes(&ic->ic_sta, remove_duplicate_nodes, ni);
if (ni->ni_associd == 0) {
u_int16_t aid;
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -216,16 +216,14 @@ ieee80211_input(struct ieee80211vap * va
type = -1; /* undefined */
- if (!vap)
- goto out;
+ if (!vap || !vap->iv_bss || !vap->iv_dev || !vap->iv_ic)
+ goto discard;
ic = vap->iv_ic;
- if (!ic)
- goto out;
-
dev = vap->iv_dev;
- if (!dev)
- goto out;
+
+ if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ goto discard;
/* initialize ni as in the previous API */
if (ni_or_null == NULL) {
@@ -233,9 +231,10 @@ ieee80211_input(struct ieee80211vap * va
* guarantee its existence during the following call, hence
* briefly grab our own reference. */
ni = ieee80211_ref_node(vap->iv_bss);
+ KASSERT(ni != NULL, ("null node"));
+ } else {
+ ni->ni_inact = ni->ni_inact_reload;
}
- KASSERT(ni != NULL, ("null node"));
- ni->ni_inact = ni->ni_inact_reload;
KASSERT(skb->len >= sizeof(struct ieee80211_frame_min),
("frame length too short: %u", skb->len));
@@ -844,10 +843,11 @@ ieee80211_input(struct ieee80211vap * va
err:
vap->iv_devstats.rx_errors++;
out:
- if (skb != NULL)
- ieee80211_dev_kfree_skb(&skb);
if (ni_or_null == NULL)
ieee80211_unref_node(&ni);
+discard:
+ if (skb != NULL)
+ ieee80211_dev_kfree_skb(&skb);
return type;
#undef HAS_SEQ
}
@@ -929,16 +929,23 @@ int
ieee80211_input_all(struct ieee80211com *ic,
struct sk_buff *skb, int rssi, u_int64_t rtsf)
{
+ struct ieee80211_frame_min *wh = (struct ieee80211_frame_min *) skb->data;
struct ieee80211vap *vap;
int type = -1;
/* XXX locking */
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ struct ieee80211_node *ni = NULL;
struct sk_buff *skb1;
if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
continue;
+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+ !IEEE80211_IS_MULTICAST(wh->i_addr1))
+ continue;
+
+ ni = ieee80211_find_rxnode(ic, vap, wh);
if (TAILQ_NEXT(vap, iv_next) != NULL) {
skb1 = skb_copy(skb, GFP_ATOMIC);
if (skb1 == NULL) {
@@ -950,8 +957,12 @@ ieee80211_input_all(struct ieee80211com
skb1 = skb;
skb = NULL;
}
- type = ieee80211_input(vap, NULL, skb1, rssi, rtsf);
+ type = ieee80211_input(vap, ni, skb1, rssi, rtsf);
+ if (ni)
+ ieee80211_unref_node(&ni);
}
+
+out:
if (skb != NULL) /* no vaps, reclaim skb */
ieee80211_dev_kfree_skb(&skb);
return type;
@@ -1147,11 +1158,9 @@ ieee80211_deliver_data(struct ieee80211_
* sending it will not work; just let it be
* delivered normally.
*/
- struct ieee80211_node *ni1 = ieee80211_find_node(
- &vap->iv_ic->ic_sta, eh->ether_dhost);
+ struct ieee80211_node *ni1 = ieee80211_find_txnode(vap, eh->ether_dhost);
if (ni1 != NULL) {
- if (ni1->ni_vap == vap &&
- ieee80211_node_is_authorized(ni1) &&
+ if (ieee80211_node_is_authorized(ni1) &&
!ni1->ni_subif &&
ni1 != vap->iv_bss) {
@@ -3520,6 +3529,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
(vap->iv_opmode == IEEE80211_M_WDS)) &&
(scan.capinfo & IEEE80211_CAPINFO_ESS))) {
struct ieee80211vap *avp = NULL;
+ int do_unref = 0;
int found = 0;
IEEE80211_LOCK_IRQ(vap->iv_ic);
@@ -3553,10 +3563,12 @@ ieee80211_recv_mgmt(struct ieee80211vap
ni->ni_associd |= 0xc000;
avp->iv_wdsnode = ieee80211_ref_node(ni);
IEEE80211_UNLOCK_IRQ(ic);
- } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
+ } else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+ IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
/* Create a new entry in the neighbor table. */
ni = ieee80211_add_neighbor(vap, wh, &scan);
}
+ do_unref = 1;
} else {
/*
* Copy data from beacon to neighbor table.
@@ -3595,6 +3607,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
ni->ni_rssi = rssi;
ni->ni_rtsf = rtsf;
ni->ni_last_rx = jiffies;
+ if (do_unref)
+ ieee80211_unref_node(&ni);
}
}
break;
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6589,9 +6589,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
-
/* Lookup the new node if any (this grabs a reference to it) */
- ni = ieee80211_find_rxnode(vap->iv_ic,
+ ni = ieee80211_find_rxnode(vap->iv_ic, vap,
(const struct ieee80211_frame_min *)skb->data);
if (ni == NULL) {
DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
@@ -6746,7 +6745,9 @@ ath_rx_poll(struct net_device *dev, int
struct ath_desc *ds;
struct ath_rx_status *rs;
struct sk_buff *skb = NULL;
+ struct ieee80211vap *vap;
struct ieee80211_node *ni;
+ const struct ieee80211_frame_min *wh;
unsigned int len;
int type;
u_int phyerr;
@@ -6901,12 +6902,15 @@ rx_accept:
skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
if (mic_fail) {
+ wh = (const struct ieee80211_frame_min *) skb->data;
+
/* Ignore control frames which are reported with mic error */
- if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
+ if ((wh->i_fc[0] &
IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
goto drop_micfail;
- ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
+ vap = ieee80211_find_rxvap(ic, wh->i_addr1);
+ ni = ieee80211_find_rxnode(ic, vap, wh);
if (ni && ni->ni_table) {
ieee80211_check_mic(ni, skb);
@@ -6968,11 +6972,24 @@ drop_micfail:
* for its use. If the sender is unknown spam the
* frame; it'll be dropped where it's not wanted.
*/
- if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
+ wh = (const struct ieee80211_frame_min *) skb->data;
+ if ((rs->rs_keyix != HAL_RXKEYIX_INVALID) &&
(ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
/* Fast path: node is present in the key map;
* grab a reference for processing the frame. */
- ni = ieee80211_ref_node(ni);
+ ieee80211_ref_node(ni);
+ if ((ATH_GET_VAP_ID(wh->i_addr1) !=
+ ATH_GET_VAP_ID(ni->ni_vap->iv_myaddr)) ||
+ ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
+ IEEE80211_FC1_DIR_DSTODS)) {
+ /* key cache node lookup is fast, but it can
+ * lead to problems in multi-bss (foreign vap
+ * node reference) or wds (wdsap node ref instead
+ * of base ap node ref).
+ * use slowpath lookup in both cases
+ */
+ goto lookup_slowpath;
+ }
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
ieee80211_unref_node(&ni);
@@ -6981,24 +6998,39 @@ drop_micfail:
* No key index or no entry, do a lookup and
* add the node to the mapping table if possible.
*/
- ni = ieee80211_find_rxnode(ic,
- (const struct ieee80211_frame_min *)skb->data);
+
+lookup_slowpath:
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+ vap = NULL;
+ else
+ vap = ieee80211_find_rxvap(ic, wh->i_addr1);
+
+ if (vap)
+ ni = ieee80211_find_rxnode(ic, vap, wh);
+ else
+ ni = NULL;
+
if (ni != NULL) {
ieee80211_keyix_t keyix;
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
- type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
+ type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
/*
* If the station has a key cache slot assigned
* update the key->node mapping table.
*/
keyix = ni->ni_ucastkey.wk_keyix;
if (keyix != IEEE80211_KEYIX_NONE &&
- sc->sc_keyixmap[keyix] == NULL)
+ sc->sc_keyixmap[keyix] == NULL) {
sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
+ }
ieee80211_unref_node(&ni);
- } else
- type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
+ } else {
+ if (vap)
+ type = ieee80211_input(vap, NULL, skb, rs->rs_rssi, bf->bf_tsf);
+ else
+ type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
+ }
}
if (sc->sc_diversity) {
--- a/net80211/ieee80211_node.h
+++ b/net80211/ieee80211_node.h
@@ -286,15 +286,18 @@ struct ieee80211_node *ieee80211_find_no
const u_int8_t *);
#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+struct ieee80211vap *
+ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac);
+
/* Returns a ieee80211_node* with refcount incremented, if found */
#ifdef IEEE80211_DEBUG_REFCNT
-#define ieee80211_find_rxnode(_nt, _wh) \
- ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__)
+#define ieee80211_find_rxnode(_nt, _vap, _wh) \
+ ieee80211_find_rxnode_debug(_nt, _vap, _wh, __func__, __LINE__)
struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *,
- const struct ieee80211_frame_min *, const char *, int);
+ struct ieee80211vap *, const struct ieee80211_frame_min *, const char *, int);
#else
struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,
- const struct ieee80211_frame_min *);
+ struct ieee80211vap *, const struct ieee80211_frame_min *);
#endif /* #ifdef IEEE80211_DEBUG_REFCNT */
/* Returns a ieee80211_node* with refcount incremented, if found */

View File

@ -0,0 +1,64 @@
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3621,6 +3621,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
vap->iv_stats.is_rx_mgtdiscard++;
return;
}
+ if (vap->iv_no_probereq)
+ return;
if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
/* frame must be directed */
vap->iv_stats.is_rx_mgtdiscard++; /* XXX: stat */
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -651,6 +651,7 @@ enum {
IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */
IEEE80211_PARAM_MAXASSOC = 83, /* maximum associated stations */
+ IEEE80211_PARAM_PROBEREQ = 84, /* enable handling of probe requests */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -198,6 +198,7 @@ struct ieee80211vap {
u_int32_t iv_debug; /* debug msg flags */
struct ieee80211_stats iv_stats; /* statistics */
+ int iv_no_probereq;
int iv_max_nodes;
int iv_monitor_nods_only; /* in monitor mode only nods traffic */
int iv_monitor_txf_len; /* in monitor mode, truncate tx packets */
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2881,6 +2881,9 @@ ieee80211_ioctl_setparam(struct net_devi
else
vap->iv_max_nodes = value;
break;
+ case IEEE80211_PARAM_PROBEREQ:
+ vap->iv_no_probereq = !value;
+ break;
#ifdef ATH_REVERSE_ENGINEERING
case IEEE80211_PARAM_DUMPREGS:
ieee80211_dump_registers(dev, info, w, extra);
@@ -3243,6 +3246,9 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_MAXASSOC:
param[0] = vap->iv_max_nodes;
break;
+ case IEEE80211_PARAM_PROBEREQ:
+ param[0] = !vap->iv_no_probereq;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -5802,6 +5808,10 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxassoc"},
{ IEEE80211_PARAM_MAXASSOC,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxassoc"},
+ { IEEE80211_PARAM_PROBEREQ,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "probereq"},
+ { IEEE80211_PARAM_PROBEREQ,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_probereq"},
#ifdef ATH_REVERSE_ENGINEERING
/*

View File

@ -0,0 +1,11 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -13534,7 +13534,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
bus_unmap_single(
sc->sc_bdev,
bf->bf_skbaddrff[i],
- (direction == BUS_DMA_TODEVICE ?
+ (direction == BUS_DMA_FROMDEVICE ?
sc->sc_rxbufsize : ffskb->len),
direction);
bf->bf_skbaddrff[i] = 0;

View File

@ -0,0 +1,65 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6734,10 +6734,10 @@ ath_rx_poll(struct net_device *dev, int
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi);
struct net_device *dev = sc->sc_dev;
- u_int rx_limit = budget;
+ int rx_limit = budget;
#else
struct ath_softc *sc = dev->priv;
- u_int rx_limit = min(dev->quota, *budget);
+ int rx_limit = min(dev->quota, *budget);
#endif
struct ath_buf *bf;
struct ieee80211com *ic = &sc->sc_ic;
@@ -6780,13 +6780,15 @@ process_rx_again:
break;
}
- if (rx_limit-- < 2) {
+ processed += ic->ic_recv;
+ rx_limit -= ic->ic_recv;
+ ic->ic_recv = 0;
+
+ /* keep a reserve for napi */
+ if (rx_limit < 4) {
early_stop = 1;
break;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- processed++;
-#endif
skb = bf->bf_skb;
if (skb == NULL) {
@@ -7074,8 +7076,8 @@ rx_next:
if (sc->sc_isr & HAL_INT_RX) {
u_int64_t hw_tsf = ath_hal_gettsf64(ah);
sc->sc_isr &= ~HAL_INT_RX;
- local_irq_restore(flags);
ath_uapsd_processtriggers(sc, hw_tsf);
+ local_irq_restore(flags);
goto process_rx_again;
}
local_irq_restore(flags);
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -1206,6 +1206,7 @@ ieee80211_deliver_data(struct ieee80211_
}
}
+ vap->iv_ic->ic_recv++;
if (skb != NULL) {
skb->dev = dev;
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -323,6 +323,7 @@ struct ieee80211com {
struct ifmedia ic_media; /* interface media config */
u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
struct timer_list ic_inact; /* mgmt/inactivity timer */
+ u_int ic_recv; /* frame received counter */
unsigned int ic_subifs;
u_int32_t ic_flags; /* state flags */

Some files were not shown because too many files have changed in this diff Show More