[PATCH 2.4] Wireless Extension v16 : 802.11a/802.11g fixes

From: Jean Tourrilhes
Date: Thu Sep 04 2003 - 12:46:51 EST


Hi Marcelo,

I really need this patch to go in 2.4.23, as many wireless
drivers need it (airo.c + various external drivers). This is super
safe as many people have tested it in 2.5.X and downloaded from my web
page.
Resend (see below), retested for 2.4.23-pre3.
Changelog :
o add more 802.11a/802.11g support (more freq/bitrates)
o improved iwspy support (used by airo.c)

Thanks in advance...

Jean

-----------------------------------------------------------

Hi Marcelo,

Could you add this in 2.4.23 ?
This patch update Wireless Extensions to v16. This is the same
patch that went into kernel 2.5.70, but rediffed and tested with
2.4.23-pre2.
This update fixes a few details for 802.11a/802.11g support,
like increasing the number of frequencies and bitrates. It also
features an improved iwspy support.
Note that airo.c included in 2.4.23-pre2 already include WE-16
support, so this patch is needed to enable this support. Of course, I
tested that airo.c works properly after the upgrade.

Thanks...

Jean

-----------------------------------------------------------------

diff -u -p linux/include/linux/wireless.15.h linux/include/linux/wireless.h
--- linux/include/linux/wireless.15.h Wed Sep 3 11:11:16 2003
+++ linux/include/linux/wireless.h Wed Sep 3 11:12:57 2003
@@ -1,7 +1,7 @@
/*
* This file define a set of standard wireless extensions
*
- * Version : 15 12.7.02
+ * Version : 16 2.4.03
*
* Authors : Jean Tourrilhes - HPL - <jt@xxxxxxxxxx>
* Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
@@ -69,6 +69,8 @@

/***************************** INCLUDES *****************************/

+/* To minimise problems in user space, I might remove those headers
+ * at some point. Jean II */
#include <linux/types.h> /* for "caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/if.h> /* for IFNAMSIZ and co... */
@@ -80,7 +82,7 @@
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
-#define WIRELESS_EXT 15
+#define WIRELESS_EXT 16

/*
* Changes :
@@ -163,6 +165,16 @@
* - Add IW_TXPOW_RANGE for range of Tx Powers
* - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
* - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
*/

/**************************** CONSTANTS ****************************/
@@ -196,9 +208,11 @@
/* SIOCGIWSTATS is strictly used between user space and the kernel, and
* is never passed to the driver (i.e. the driver will never see it). */

-/* Mobile IP support (statistics per MAC address) */
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
#define SIOCSIWSPY 0x8B10 /* set spy addresses */
#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */

/* Access Point manipulation */
#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
@@ -294,7 +308,7 @@
#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */

-#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */

#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */

@@ -306,13 +320,13 @@
/* ----------------------- OTHER CONSTANTS ----------------------- */

/* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES 16
+#define IW_MAX_FREQUENCIES 32
/* Note : if you have something like 80 frequencies,
* don't increase this constant and don't fill the frequency list.
* The user will be able to set by channel anyway... */

/* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES 8
+#define IW_MAX_BITRATES 32

/* Maximum tx powers in the range struct */
#define IW_MAX_TXPOWER 8
@@ -320,8 +334,7 @@
* a few of them in the struct iw_range. */

/* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY 8 /* set */
-#define IW_MAX_GET_SPY 64 /* get */
+#define IW_MAX_SPY 8

/* Maximum of address that you may get in the
list of access points in range */
@@ -354,7 +367,8 @@
#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */

/* Power management flags available (along with the value, if any) */
#define IW_POWER_ON 0x0000 /* No details... */
@@ -482,6 +496,17 @@ struct iw_missed
__u32 beacon; /* Missed beacons/superframe */
};

+/*
+ * Quality range (for spy threshold)
+ */
+struct iw_thrspy
+{
+ struct sockaddr addr; /* Source address (hw/mac) */
+ struct iw_quality qual; /* Quality of the link */
+ struct iw_quality low; /* Low threshold */
+ struct iw_quality high; /* High threshold */
+};
+
/* ------------------------ WIRELESS STATS ------------------------ */
/*
* Wireless statistics (used for /proc/net/wireless)
@@ -534,7 +559,7 @@ union iwreq_data
struct iw_quality qual; /* Quality part of statistics */

struct sockaddr ap_addr; /* Access point address */
- struct sockaddr addr; /* Destination address (hw) */
+ struct sockaddr addr; /* Destination address (hw/mac) */

struct iw_param param; /* Other small parameters */
struct iw_point data; /* Other large parameters */
@@ -582,17 +607,31 @@ struct iw_range
__u32 min_nwid; /* Minimal NWID we are able to set */
__u32 max_nwid; /* Maximal NWID we are able to set */

- /* Frequency */
- __u16 num_channels; /* Number of channels [0; num - 1] */
- __u8 num_frequency; /* Number of entry in the list */
- struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
- /* Note : this frequency list doesn't need to fit channel numbers */
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+ /* Filler to keep "version" at the same offset */
+ __s32 old_freq[6];

/* signal level threshold range */
__s32 sensitivity;

/* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
struct iw_quality max_qual; /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ struct iw_quality avg_qual; /* Quality of the link */

/* Rates */
__u8 num_bitrates; /* Number of entries in the list */
@@ -619,6 +658,8 @@ struct iw_range
__u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
__u8 num_encoding_sizes; /* Number of entry in the list */
__u8 max_encoding_tokens; /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ __u8 encoding_login_index; /* token index for login token */

/* Transmit power */
__u16 txpower_capa; /* What options are supported */
@@ -638,18 +679,12 @@ struct iw_range
__s32 min_r_time; /* Minimal retry lifetime */
__s32 max_r_time; /* Maximal retry lifetime */

- /* Average quality of link & SNR */
- struct iw_quality avg_qual; /* Quality of the link */
- /* This should contain the average/typical values of the quality
- * indicator. This should be the threshold between a "good" and
- * a "bad" link (example : monitor going from green to orange).
- * Currently, user space apps like quality monitors don't have any
- * way to calibrate the measurement. With this, they can split
- * the range between 0 and max_qual in different quality level
- * (using a geometric subdivision centered on the average).
- * I expect that people doing the user space apps will feedback
- * us on which value we need to put in each driver...
- */
+ /* Frequency */
+ __u16 num_channels; /* Number of channels [0; num - 1] */
+ __u8 num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
};

/*
diff -u -p linux/include/net/iw_handler.15.h linux/include/net/iw_handler.h
--- linux/include/net/iw_handler.15.h Wed Sep 3 11:11:32 2003
+++ linux/include/net/iw_handler.h Wed Sep 3 11:12:57 2003
@@ -1,7 +1,7 @@
/*
* This file define the new driver API for Wireless Extensions
*
- * Version : 4 21.6.02
+ * Version : 5 4.12.02
*
* Authors : Jean Tourrilhes - HPL - <jt@xxxxxxxxxx>
* Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
@@ -206,7 +206,7 @@
* will be needed...
* I just plan to increment with each new version.
*/
-#define IW_HANDLER_VERSION 4
+#define IW_HANDLER_VERSION 5

/*
* Changes :
@@ -220,10 +220,18 @@
* V3 to V4
* --------
* - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
+ *
+ * V4 to V5
+ * --------
+ * - Add new spy support : struct iw_spy_data & prototypes
*/

/**************************** CONSTANTS ****************************/

+/* Enable enhanced spy support. Disable to reduce footprint */
+#define IW_WIRELESS_SPY
+#define IW_WIRELESS_THRSPY
+
/* Special error message for the driver to indicate that we
* should do a commit after return from the iw_handler */
#define EIWCOMMIT EINPROGRESS
@@ -315,6 +323,9 @@ struct iw_handler_def
* We will automatically export that to user space... */
struct iw_priv_args * private_args;

+ /* Driver enhanced spy support */
+ long spy_offset; /* Spy data offset */
+
/* In the long term, get_wireless_stats will move from
* 'struct net_device' to here, to minimise bloat. */
};
@@ -350,6 +361,33 @@ struct iw_ioctl_description

/* Need to think of short header translation table. Later. */

+/* --------------------- ENHANCED SPY SUPPORT --------------------- */
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to include this struct in its private part and use the
+ * standard spy iw_handler.
+ */
+
+/*
+ * Instance specific spy data, i.e. addresses spied and quality for them.
+ */
+struct iw_spy_data
+{
+#ifdef IW_WIRELESS_SPY
+ /* --- Standard spy support --- */
+ int spy_number;
+ u_char spy_address[IW_MAX_SPY][ETH_ALEN];
+ struct iw_quality spy_stat[IW_MAX_SPY];
+#ifdef IW_WIRELESS_THRSPY
+ /* --- Enhanced spy support (event) */
+ struct iw_quality spy_thr_low; /* Low threshold */
+ struct iw_quality spy_thr_high; /* High threshold */
+ u_char spy_thr_under[IW_MAX_SPY];
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+};
+
/**************************** PROTOTYPES ****************************/
/*
* Functions part of the Wireless Extensions (defined in net/core/wireless.c).
@@ -375,6 +413,31 @@ extern void wireless_send_event(struct n

/* We may need a function to send a stream of events to user space.
* More on that later... */
+
+/* Standard handler for SIOCSIWSPY */
+extern int iw_handler_set_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Standard handler for SIOCGIWSPY */
+extern int iw_handler_get_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Standard handler for SIOCSIWTHRSPY */
+extern int iw_handler_set_thrspy(struct net_device * dev,
+ struct iw_request_info *info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Standard handler for SIOCGIWTHRSPY */
+extern int iw_handler_get_thrspy(struct net_device * dev,
+ struct iw_request_info *info,
+ union iwreq_data * wrqu,
+ char * extra);
+/* Driver call to update spy records */
+extern void wireless_spy_update(struct net_device * dev,
+ unsigned char * address,
+ struct iw_quality * wstats);

/************************* INLINE FUNTIONS *************************/
/*
diff -u -p linux/net/core/wireless.15.c linux/net/core/wireless.c
--- linux/net/core/wireless.15.c Wed Sep 3 11:11:52 2003
+++ linux/net/core/wireless.c Wed Sep 3 11:12:57 2003
@@ -2,7 +2,7 @@
* This file implement the Wireless Extensions APIs.
*
* Authors : Jean Tourrilhes - HPL - <jt@xxxxxxxxxx>
- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
*
* (As all part of the Linux kernel, this file is GPL)
*/
@@ -43,6 +43,11 @@
* o Turn on WE_STRICT_WRITE by default + kernel warning
* o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
* o Fix off-by-one in test (extra_size <= IFNAMSIZ)
+ *
+ * v6 - 9.01.03 - Jean II
+ * o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
+ * o Add enhanced spy support : iw_handler_set_thrspy() and event.
+ * o Add WIRELESS_EXT version display in /proc/net/wireless
*/

/***************************** INCLUDES *****************************/
@@ -52,6 +57,7 @@
#include <linux/types.h> /* off_t */
#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
#include <linux/rtnetlink.h> /* rtnetlink stuff */
+#include <linux/if_arp.h> /* ARPHRD_ETHER */

#include <linux/wireless.h> /* Pretty obvious */
#include <net/iw_handler.h> /* New driver API */
@@ -65,6 +71,7 @@
/* Debuging stuff */
#undef WE_IOCTL_DEBUG /* Debug IOCTL API */
#undef WE_EVENT_DEBUG /* Debug Event dispatcher */
+#undef WE_SPY_DEBUG /* Debug enhanced spy support */

/* Options */
#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */
@@ -72,7 +79,7 @@

/************************* GLOBAL VARIABLES *************************/
/*
- * You should not use global variables, because or re-entrancy.
+ * You should not use global variables, because of re-entrancy.
* On our case, it's only const, so it's OK...
*/
/*
@@ -115,11 +122,11 @@ static const struct iw_ioctl_description
/* SIOCSIWSPY */
{ IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
/* SIOCGIWSPY */
- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
- /* -- hole -- */
- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
- /* -- hole -- */
- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
+ /* SIOCSIWTHRSPY */
+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
+ /* SIOCGIWTHRSPY */
+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
/* SIOCSIWAP */
{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
/* SIOCGIWAP */
@@ -377,9 +384,9 @@ int dev_get_wireless_info(char * buffer,
struct net_device * dev;

size = sprintf(buffer,
- "Inter-| sta-| Quality | Discarded packets | Missed\n"
- " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
- );
+ "Inter-| sta-| Quality | Discarded packets | Missed | WE\n"
+ " face | tus | link level noise | nwid crypt frag retry misc | beacon | %d\n",
+ WIRELESS_EXT);

pos += size;
len += size;
@@ -1023,4 +1030,253 @@ void wireless_send_event(struct net_devi
kfree(event);

return; /* Always success, I guess ;-) */
+}
+
+/********************** ENHANCED IWSPY SUPPORT **********************/
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to use those standard spy iw_handler in struct iw_handler_def,
+ * push data to us via XXX and include struct iw_spy_data in its
+ * private part.
+ * One of the main advantage of centralising spy support here is that
+ * it becomes much easier to improve and extend it without having to touch
+ * the drivers. One example is the addition of the Spy-Threshold events.
+ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set Spy List
+ */
+int iw_handler_set_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra)
+{
+#ifdef IW_WIRELESS_SPY
+ struct iw_spy_data * spydata = (dev->priv +
+ dev->wireless_handlers->spy_offset);
+ struct sockaddr * address = (struct sockaddr *) extra;
+
+ /* Disable spy collection while we copy the addresses.
+ * As we don't disable interrupts, we need to do this to avoid races.
+ * As we are the only writer, this is good enough. */
+ spydata->spy_number = 0;
+
+ /* Are there are addresses to copy? */
+ if(wrqu->data.length > 0) {
+ int i;
+
+ /* Copy addresses */
+ for(i = 0; i < wrqu->data.length; i++)
+ memcpy(spydata->spy_address[i], address[i].sa_data,
+ ETH_ALEN);
+ /* Reset stats */
+ memset(spydata->spy_stat, 0,
+ sizeof(struct iw_quality) * IW_MAX_SPY);
+
+#ifdef WE_SPY_DEBUG
+ printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
+ for (i = 0; i < wrqu->data.length; i++)
+ printk(KERN_DEBUG
+ "%02X:%02X:%02X:%02X:%02X:%02X \n",
+ spydata->spy_address[i][0],
+ spydata->spy_address[i][1],
+ spydata->spy_address[i][2],
+ spydata->spy_address[i][3],
+ spydata->spy_address[i][4],
+ spydata->spy_address[i][5]);
+#endif /* WE_SPY_DEBUG */
+ }
+ /* Enable addresses */
+ spydata->spy_number = wrqu->data.length;
+
+ return 0;
+#else /* IW_WIRELESS_SPY */
+ return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get Spy List
+ */
+int iw_handler_get_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra)
+{
+#ifdef IW_WIRELESS_SPY
+ struct iw_spy_data * spydata = (dev->priv +
+ dev->wireless_handlers->spy_offset);
+ struct sockaddr * address = (struct sockaddr *) extra;
+ int i;
+
+ wrqu->data.length = spydata->spy_number;
+
+ /* Copy addresses. */
+ for(i = 0; i < spydata->spy_number; i++) {
+ memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
+ address[i].sa_family = AF_UNIX;
+ }
+ /* Copy stats to the user buffer (just after). */
+ if(spydata->spy_number > 0)
+ memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number),
+ spydata->spy_stat,
+ sizeof(struct iw_quality) * spydata->spy_number);
+ /* Reset updated flags. */
+ for(i = 0; i < spydata->spy_number; i++)
+ spydata->spy_stat[i].updated = 0;
+ return 0;
+#else /* IW_WIRELESS_SPY */
+ return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set spy threshold
+ */
+int iw_handler_set_thrspy(struct net_device * dev,
+ struct iw_request_info *info,
+ union iwreq_data * wrqu,
+ char * extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+ struct iw_spy_data * spydata = (dev->priv +
+ dev->wireless_handlers->spy_offset);
+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
+
+ /* Just do it */
+ memcpy(&(spydata->spy_thr_low), &(threshold->low),
+ 2 * sizeof(struct iw_quality));
+
+ /* Clear flag */
+ memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
+
+#ifdef WE_SPY_DEBUG
+ printk(KERN_DEBUG "iw_handler_set_thrspy() : low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
+#endif /* WE_SPY_DEBUG */
+
+ return 0;
+#else /* IW_WIRELESS_THRSPY */
+ return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get spy threshold
+ */
+int iw_handler_get_thrspy(struct net_device * dev,
+ struct iw_request_info *info,
+ union iwreq_data * wrqu,
+ char * extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+ struct iw_spy_data * spydata = (dev->priv +
+ dev->wireless_handlers->spy_offset);
+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
+
+ /* Just do it */
+ memcpy(&(threshold->low), &(spydata->spy_thr_low),
+ 2 * sizeof(struct iw_quality));
+
+ return 0;
+#else /* IW_WIRELESS_THRSPY */
+ return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+#ifdef IW_WIRELESS_THRSPY
+/*------------------------------------------------------------------*/
+/*
+ * Prepare and send a Spy Threshold event
+ */
+static void iw_send_thrspy_event(struct net_device * dev,
+ struct iw_spy_data * spydata,
+ unsigned char * address,
+ struct iw_quality * wstats)
+{
+ union iwreq_data wrqu;
+ struct iw_thrspy threshold;
+
+ /* Init */
+ wrqu.data.length = 1;
+ wrqu.data.flags = 0;
+ /* Copy address */
+ memcpy(threshold.addr.sa_data, address, ETH_ALEN);
+ threshold.addr.sa_family = ARPHRD_ETHER;
+ /* Copy stats */
+ memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
+ /* Copy also thresholds */
+ memcpy(&(threshold.low), &(spydata->spy_thr_low),
+ 2 * sizeof(struct iw_quality));
+
+#ifdef WE_SPY_DEBUG
+ printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
+ threshold.addr.sa_data[0],
+ threshold.addr.sa_data[1],
+ threshold.addr.sa_data[2],
+ threshold.addr.sa_data[3],
+ threshold.addr.sa_data[4],
+ threshold.addr.sa_data[5], threshold.qual.level);
+#endif /* WE_SPY_DEBUG */
+
+ /* Send event to user space */
+ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
+}
+#endif /* IW_WIRELESS_THRSPY */
+
+/* ---------------------------------------------------------------- */
+/*
+ * Call for the driver to update the spy data.
+ * For now, the spy data is a simple array. As the size of the array is
+ * small, this is good enough. If we wanted to support larger number of
+ * spy addresses, we should use something more efficient...
+ */
+void wireless_spy_update(struct net_device * dev,
+ unsigned char * address,
+ struct iw_quality * wstats)
+{
+#ifdef IW_WIRELESS_SPY
+ struct iw_spy_data * spydata = (dev->priv +
+ dev->wireless_handlers->spy_offset);
+ int i;
+ int match = -1;
+
+#ifdef WE_SPY_DEBUG
+ printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
+#endif /* WE_SPY_DEBUG */
+
+ /* Update all records that match */
+ for(i = 0; i < spydata->spy_number; i++)
+ if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
+ memcpy(&(spydata->spy_stat[i]), wstats,
+ sizeof(struct iw_quality));
+ match = i;
+ }
+#ifdef IW_WIRELESS_THRSPY
+ /* Generate an event if we cross the spy threshold.
+ * To avoid event storms, we have a simple hysteresis : we generate
+ * event only when we go under the low threshold or above the
+ * high threshold. */
+ if(match >= 0) {
+ if(spydata->spy_thr_under[match]) {
+ if(wstats->level > spydata->spy_thr_high.level) {
+ spydata->spy_thr_under[match] = 0;
+ iw_send_thrspy_event(dev, spydata,
+ address, wstats);
+ }
+ } else {
+ if(wstats->level < spydata->spy_thr_low.level) {
+ spydata->spy_thr_under[match] = 1;
+ iw_send_thrspy_event(dev, spydata,
+ address, wstats);
+ }
+ }
+ }
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
}
diff -u -p linux/net/netsyms.15.c linux/net/netsyms.c
--- linux/net/netsyms.15.c Wed Sep 3 11:12:24 2003
+++ linux/net/netsyms.c Wed Sep 3 11:12:57 2003
@@ -612,6 +612,11 @@ EXPORT_SYMBOL(softnet_data);
#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
#include <net/iw_handler.h>
EXPORT_SYMBOL(wireless_send_event);
+EXPORT_SYMBOL(iw_handler_set_spy);
+EXPORT_SYMBOL(iw_handler_get_spy);
+EXPORT_SYMBOL(iw_handler_set_thrspy);
+EXPORT_SYMBOL(iw_handler_get_thrspy);
+EXPORT_SYMBOL(wireless_spy_update);
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */

/* ethtool.c */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/