[PATCH]: hostapd with madwifi accounting
Gunter Burchardt
gbur
Thu Oct 7 23:08:22 PDT 2004
Hello,
Here are two patches to enable madwifi and hostapd to account station
traffic. I added /proc/net/madwifi/athX/<station mac> to madwifi driver.
Hostapd uses these files to get accounting information of a station. To
use /proc/net/hostap/athX like as suggested in driver_madwifi.c is not
good in my opinion. If hostap and madwifi driver is used together each
driver can remove /proc/net/hostap if driver module is unloaded.
Secondly i added a (custom) netlink message with accounting information
sent just before madwifi tells hostapd that a station leaves. This is
nessesary because madwifi deletes procfs entry for the station before
hostapd reads accounting information.
regards
gunter
-------------- next part --------------
diff -Nur madwifi.old/ath/if_ath.c madwifi/ath/if_ath.c
--- madwifi.old/ath/if_ath.c 2004-09-28 06:49:54.000000000 +0200
+++ madwifi/ath/if_ath.c 2004-10-08 07:22:49.000000000 +0200
@@ -167,6 +167,8 @@
static void ath_dynamic_sysctl_unregister(struct ath_softc *);
#endif /* CONFIG_SYSCTL */
+static struct proc_dir_entry *proc_net_madwifi;
+
static const char *acnames[] = {
"WME_AC_BE",
"WME_AC_BK",
@@ -533,6 +535,12 @@
ath_dynamic_sysctl_register(sc);
ieee80211_sysctl_register(ic);
#endif /* CONFIG_SYSCTL */
+ ic->proc = proc_mkdir(dev->name, proc_net_madwifi);
+ if(!ic->proc){
+ printk(KERN_ERR "%s: unable to register procfs\n", dev->name);
+ } else {
+ printk(KERN_ERR "%s: registered procfs\n", dev->name);
+ }
ieee80211_announce(ic);
ath_announce(dev);
return 0;
@@ -565,6 +573,9 @@
struct ieee80211com *ic = &sc->sc_ic;
int i;
+ if(ic->proc)
+ remove_proc_entry(dev->name, proc_net_madwifi);
+
DPRINTF(sc, ATH_DEBUG_ANY, "%s: flags %x\n", __func__, dev->flags);
ath_stop(dev);
sc->sc_invalid = 1;
@@ -4589,4 +4600,17 @@
if (ath_sysctl_header)
unregister_sysctl_table(ath_sysctl_header);
}
+
+void
+ath_proc_register_madwifi(void)
+{
+ proc_net_madwifi = proc_mkdir("madwifi", proc_net);
+}
+
+void
+ath_proc_unregister_madwifi(void)
+{
+ remove_proc_entry("madwifi", proc_net);
+}
+
#endif /* CONFIG_SYSCTL */
diff -Nur madwifi.old/ath/if_ath_pci.c madwifi/ath/if_ath_pci.c
--- madwifi.old/ath/if_ath_pci.c 2004-08-20 23:28:46.000000000 +0200
+++ madwifi/ath/if_ath_pci.c 2004-10-08 07:22:49.000000000 +0200
@@ -316,10 +316,13 @@
init_ath_pci(void)
{
printk(KERN_INFO "%s: %s\n", dev_info, version);
+
+ ath_proc_register_madwifi();
if (pci_register_driver(&ath_pci_drv_id) <= 0) {
printk("ath_pci: No devices found, driver not installed.\n");
pci_unregister_driver(&ath_pci_drv_id);
+ ath_proc_unregister_madwifi();
return (-ENODEV);
}
#ifdef CONFIG_SYSCTL
@@ -332,6 +335,7 @@
static void __exit
exit_ath_pci(void)
{
+ ath_proc_unregister_madwifi();
#ifdef CONFIG_SYSCTL
ath_sysctl_unregister();
#endif
diff -Nur madwifi.old/ath/if_athvar.h madwifi/ath/if_athvar.h
--- madwifi.old/ath/if_athvar.h 2004-09-24 18:45:53.000000000 +0200
+++ madwifi/ath/if_athvar.h 2004-10-08 07:22:49.000000000 +0200
@@ -293,7 +293,8 @@
void ath_sysctl_register(void);
void ath_sysctl_unregister(void);
#endif /* CONFIG_SYSCTL */
-
+void ath_proc_register_madwifi(void);
+void ath_proc_unregister_madwifi(void);
/*
* HAL definitions to comply with local coding convention.
*/
diff -Nur madwifi.old/net80211/ieee80211_input.c madwifi/net80211/ieee80211_input.c
--- madwifi.old/net80211/ieee80211_input.c 2004-09-14 04:06:06.000000000 +0200
+++ madwifi/net80211/ieee80211_input.c 2004-10-08 07:22:49.000000000 +0200
@@ -313,6 +313,9 @@
ic->ic_stats.is_rx_notassoc++;
goto err;
}
+ ni->ni_stats.ns_rx_data++;
+ ni->ni_stats.ns_rx_bytes += skb->len -
+ sizeof(struct ieee80211_frame);
break;
default:
/* XXX here to keep compiler happy */
diff -Nur madwifi.old/net80211/ieee80211_linux.c madwifi/net80211/ieee80211_linux.c
--- madwifi.old/net80211/ieee80211_linux.c 2004-09-24 18:45:53.000000000 +0200
+++ madwifi/net80211/ieee80211_linux.c 2004-10-08 07:22:49.000000000 +0200
@@ -166,6 +166,27 @@
}
void
+ieee80211_notify_traffic_statistic(struct ieee80211com *ic,
+ struct ieee80211_node *ni)
+{
+ static const char * tag = "STA-TRAFFIC-STAT";
+ union iwreq_data wrqu;
+ char buf[128]; /* max message < 125 byte */
+
+ snprintf(buf, sizeof(buf), "%s\nmac=%s\n"
+ "rx_packets=%u\ntx_packets=%u\n"
+ "rx_bytes=%u\ntx_bytes=%u\n",
+ tag, ether_sprintf(ni->ni_macaddr),
+ ni->ni_stats.ns_rx_data, ni->ni_stats.ns_tx_data,
+ (u_int32_t)ni->ni_stats.ns_rx_bytes,
+ (u_int32_t)ni->ni_stats.ns_tx_bytes);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(buf);
+ wireless_send_event(ic->ic_dev, IWEVCUSTOM, &wrqu, buf);
+}
+
+void
ieee80211_notify_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
{
union iwreq_data wreq;
@@ -176,6 +197,8 @@
wreq.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(ic->ic_dev, SIOCGIWAP, &wreq, NULL);
} else {
+ /* sending message about last traffic statistics of station */
+ ieee80211_notify_traffic_statistic(ic, ni);
/* fire off wireless event station leaving */
memset(&wreq, 0, sizeof(wreq));
IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
diff -Nur madwifi.old/net80211/ieee80211_node.c madwifi/net80211/ieee80211_node.c
--- madwifi.old/net80211/ieee80211_node.c 2004-09-14 04:06:06.000000000 +0200
+++ madwifi/net80211/ieee80211_node.c 2004-10-08 07:41:56.000000000 +0200
@@ -46,6 +46,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/random.h>
+#include <linux/proc_fs.h>
#include "if_media.h"
@@ -595,6 +596,7 @@
#define N(a) (sizeof(a)/sizeof(a[0]))
int i;
+ remove_proc_entry(ether_sprintf(ni->ni_macaddr), ic->proc);
ni->ni_flags = 0;
ni->ni_associd = 0;
ni->ni_esslen = 0;
@@ -1064,6 +1066,33 @@
ni->ni_flags |= IEEE80211_NODE_ERP;
}
+static int
+ieee80211_node_read_ni_info(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ char *p = page;
+ struct ieee80211_node *ni = (struct ieee80211_node *) data;
+
+ /* FIX: possible race condition.. the STA data could have just expired,
+ * but proc entry was still here so that the read could have started;
+ * some locking should be done here.. */
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "STA=%s\n", ether_sprintf(ni->ni_macaddr));
+
+ p += sprintf(p, "rx_packets=%u\ntx_packets=%u\n"
+ "rx_bytes=%u\ntx_bytes=%u\n",
+ ni->ni_stats.ns_rx_data, ni->ni_stats.ns_tx_data,
+ (u_int32_t)ni->ni_stats.ns_rx_bytes, (u_int32_t)ni->ni_stats.ns_tx_bytes);
+
+
+ return (p - page);
+}
+
+
void
ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp)
{
@@ -1092,6 +1121,9 @@
newassoc = 1;
if (ic->ic_curmode == IEEE80211_MODE_11G)
ieee80211_node_join_11g(ic, ni);
+ /* add procfs entry */
+ ni->proc = create_proc_read_entry(ether_sprintf(ni->ni_macaddr), 0,
+ ic->proc, ieee80211_node_read_ni_info, ni);
} else
newassoc = 0;
diff -Nur madwifi.old/net80211/ieee80211_node.h madwifi/net80211/ieee80211_node.h
--- madwifi.old/net80211/ieee80211_node.h 2004-09-14 04:06:06.000000000 +0200
+++ madwifi/net80211/ieee80211_node.h 2004-10-08 07:22:49.000000000 +0200
@@ -145,6 +145,7 @@
int ni_inact; /* current inactivity count */
int ni_txrate; /* index to ni_rates[] */
struct ieee80211_nodestats ni_stats; /* per-node statistics */
+ struct proc_dir_entry *proc;
};
MALLOC_DECLARE(M_80211_NODE);
diff -Nur madwifi.old/net80211/ieee80211_output.c madwifi/net80211/ieee80211_output.c
--- madwifi.old/net80211/ieee80211_output.c 2004-08-18 03:17:22.000000000 +0200
+++ madwifi/net80211/ieee80211_output.c 2004-10-08 07:22:49.000000000 +0200
@@ -361,6 +361,9 @@
*/
ni->ni_inact = ic->ic_inact_run;
}
+ /* XXX accounting output (ni->tx_bytes, ni->tx_patckets) */
+ ni->ni_stats.ns_tx_data++;
+ ni->ni_stats.ns_tx_bytes += skb->len - sizeof(struct ieee80211_frame);
*pni = ni;
return skb;
bad:
diff -Nur madwifi.old/net80211/ieee80211_var.h madwifi/net80211/ieee80211_var.h
--- madwifi.old/net80211/ieee80211_var.h 2004-08-18 03:17:22.000000000 +0200
+++ madwifi/net80211/ieee80211_var.h 2004-10-08 07:22:49.000000000 +0200
@@ -305,6 +305,7 @@
*/
const struct ieee80211_aclator *ic_acl;
void *ic_as;
+ struct proc_dir_entry *proc;
};
#define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
-------------- next part --------------
diff -Nur hostap/hostapd/driver_madwifi.c hostap.old/hostapd/driver_madwifi.c
--- hostap/hostapd/driver_madwifi.c 2004-09-21 05:37:27.000000000 +0200
+++ hostap.old/hostapd/driver_madwifi.c 2004-10-08 07:10:53.000000000 +0200
@@ -52,6 +52,8 @@
struct l2_packet_data *sock_recv; /* raw packet recv socket */
int ioctl_sock; /* socket for ioctl() use */
int wext_sock; /* socket for wireless events */
+ u8 acct_mac[6];
+ struct hostap_sta_driver_data acct_data;
};
static const struct driver_ops madwifi_driver_ops;
@@ -465,12 +467,16 @@
unsigned long val;
memset(data, 0, sizeof(*data));
- snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR,
+ snprintf(buf, sizeof(buf), "/proc/net/madwifi/%s/" MACSTR,
drv->iface, MAC2STR(addr));
f = fopen(buf, "r");
- if (!f)
- return -1;
+ if (!f) {
+ if( memcmp(addr, drv->acct_mac, 6) != 0 )
+ return -1;
+ *data = drv->acct_data;
+ return 0;
+ }
/* Need to read proc file with in one piece, so use large enough
* buffer. */
setbuffer(f, buf, sizeof(buf));
@@ -648,6 +654,30 @@
"with invalid MAC address");
}
}
+ if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) {
+ char *key, *value;
+ u32 val;
+ key = custom;
+ while((key=strchr(key,'\n')) != NULL) {
+ key++;
+ value = strchr(key,'=');
+ if(!value)
+ continue;
+ *value++ = 0;
+ val = strtoul(value, NULL, 10);
+ if (strcmp(key, "mac") == 0)
+ hwaddr_aton(value, drv->acct_mac);
+ else if (strcmp(key, "rx_packets") == 0)
+ drv->acct_data.rx_packets = val;
+ else if (strcmp(key, "tx_packets") == 0)
+ drv->acct_data.tx_packets = val;
+ else if (strcmp(key, "rx_bytes") == 0)
+ drv->acct_data.rx_bytes = val;
+ else if (strcmp(key, "tx_bytes") == 0)
+ drv->acct_data.tx_bytes = val;
+ key = value;
+ }
+ }
}
static void
More information about the Hostap
mailing list