[PATCH]: hostapd with madwifi accounting

Gunter Burchardt gbur at informatik.uni-rostock.de
Fri Oct 8 02:08:22 EDT 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