xref: /dflybsd-src/sys/netproto/802_11/wlan/ieee80211_alq.c (revision 085ff963b243cbeba68069d0b25c2b798c566b31)
1*085ff963SMatthew Dillon /*-
2*085ff963SMatthew Dillon  * Copyright (c) 2011 Adrian Chadd, Xenion Lty Ltd
3*085ff963SMatthew Dillon  * All rights reserved.
4*085ff963SMatthew Dillon  *
5*085ff963SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
6*085ff963SMatthew Dillon  * modification, are permitted provided that the following conditions
7*085ff963SMatthew Dillon  * are met:
8*085ff963SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
9*085ff963SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
10*085ff963SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
11*085ff963SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
12*085ff963SMatthew Dillon  *    documentation and/or other materials provided with the distribution.
13*085ff963SMatthew Dillon  *
14*085ff963SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*085ff963SMatthew Dillon  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*085ff963SMatthew Dillon  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*085ff963SMatthew Dillon  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*085ff963SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*085ff963SMatthew Dillon  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*085ff963SMatthew Dillon  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*085ff963SMatthew Dillon  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*085ff963SMatthew Dillon  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*085ff963SMatthew Dillon  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*085ff963SMatthew Dillon  */
25*085ff963SMatthew Dillon 
26*085ff963SMatthew Dillon #include <sys/cdefs.h>
27*085ff963SMatthew Dillon #ifdef __FreeBSD__
28*085ff963SMatthew Dillon __FBSDID("$FreeBSD$");
29*085ff963SMatthew Dillon #endif
30*085ff963SMatthew Dillon 
31*085ff963SMatthew Dillon /*
32*085ff963SMatthew Dillon  * net80211 fast-logging support, primarily for debugging.
33*085ff963SMatthew Dillon  *
34*085ff963SMatthew Dillon  * This implements a single debugging queue which includes
35*085ff963SMatthew Dillon  * per-device enumeration where needed.
36*085ff963SMatthew Dillon  */
37*085ff963SMatthew Dillon 
38*085ff963SMatthew Dillon #include "opt_wlan.h"
39*085ff963SMatthew Dillon 
40*085ff963SMatthew Dillon #include <sys/param.h>
41*085ff963SMatthew Dillon #include <sys/systm.h>
42*085ff963SMatthew Dillon #include <sys/mbuf.h>
43*085ff963SMatthew Dillon #include <sys/malloc.h>
44*085ff963SMatthew Dillon #include <sys/endian.h>
45*085ff963SMatthew Dillon #include <sys/kernel.h>
46*085ff963SMatthew Dillon #include <sys/sysctl.h>
47*085ff963SMatthew Dillon #include <sys/pcpu.h>
48*085ff963SMatthew Dillon #include <sys/proc.h>
49*085ff963SMatthew Dillon #include <sys/ucred.h>
50*085ff963SMatthew Dillon #include <sys/alq.h>
51*085ff963SMatthew Dillon 
52*085ff963SMatthew Dillon #include <sys/socket.h>
53*085ff963SMatthew Dillon 
54*085ff963SMatthew Dillon #include <net/if.h>
55*085ff963SMatthew Dillon #include <net/if_var.h>
56*085ff963SMatthew Dillon #include <net/if_media.h>
57*085ff963SMatthew Dillon #include <net/ethernet.h>
58*085ff963SMatthew Dillon 
59*085ff963SMatthew Dillon #include <netproto/802_11/ieee80211_var.h>
60*085ff963SMatthew Dillon #include <netproto/802_11/ieee80211_freebsd.h>
61*085ff963SMatthew Dillon #include <netproto/802_11/ieee80211_alq.h>
62*085ff963SMatthew Dillon 
63*085ff963SMatthew Dillon static struct alq *ieee80211_alq;
64*085ff963SMatthew Dillon static int ieee80211_alq_lost;
65*085ff963SMatthew Dillon static int ieee80211_alq_logged;
66*085ff963SMatthew Dillon static char ieee80211_alq_logfile[MAXPATHLEN] = "/tmp/net80211.log";
67*085ff963SMatthew Dillon static unsigned int ieee80211_alq_qsize = 64*1024;
68*085ff963SMatthew Dillon 
69*085ff963SMatthew Dillon static int
ieee80211_alq_setlogging(int enable)70*085ff963SMatthew Dillon ieee80211_alq_setlogging(int enable)
71*085ff963SMatthew Dillon {
72*085ff963SMatthew Dillon 	int error;
73*085ff963SMatthew Dillon 
74*085ff963SMatthew Dillon 	if (enable) {
75*085ff963SMatthew Dillon 		if (ieee80211_alq)
76*085ff963SMatthew Dillon 			alq_close(ieee80211_alq);
77*085ff963SMatthew Dillon 
78*085ff963SMatthew Dillon 		error = alq_open(&ieee80211_alq,
79*085ff963SMatthew Dillon 		    ieee80211_alq_logfile,
80*085ff963SMatthew Dillon 		    curthread->td_ucred,
81*085ff963SMatthew Dillon 		    ALQ_DEFAULT_CMODE,
82*085ff963SMatthew Dillon 		    sizeof (struct ieee80211_alq_rec),
83*085ff963SMatthew Dillon 		    ieee80211_alq_qsize);
84*085ff963SMatthew Dillon 		ieee80211_alq_lost = 0;
85*085ff963SMatthew Dillon 		ieee80211_alq_logged = 0;
86*085ff963SMatthew Dillon 		kprintf("net80211: logging to %s enabled; "
87*085ff963SMatthew Dillon 		    "struct size %d bytes\n",
88*085ff963SMatthew Dillon 		    ieee80211_alq_logfile,
89*085ff963SMatthew Dillon 		    sizeof(struct ieee80211_alq_rec));
90*085ff963SMatthew Dillon 	} else {
91*085ff963SMatthew Dillon 		if (ieee80211_alq)
92*085ff963SMatthew Dillon 			alq_close(ieee80211_alq);
93*085ff963SMatthew Dillon 		ieee80211_alq = NULL;
94*085ff963SMatthew Dillon 		kprintf("net80211: logging disabled\n");
95*085ff963SMatthew Dillon 		error = 0;
96*085ff963SMatthew Dillon 	}
97*085ff963SMatthew Dillon 	return (error);
98*085ff963SMatthew Dillon }
99*085ff963SMatthew Dillon 
100*085ff963SMatthew Dillon static int
sysctl_ieee80211_alq_log(SYSCTL_HANDLER_ARGS)101*085ff963SMatthew Dillon sysctl_ieee80211_alq_log(SYSCTL_HANDLER_ARGS)
102*085ff963SMatthew Dillon {
103*085ff963SMatthew Dillon 	int error, enable;
104*085ff963SMatthew Dillon 
105*085ff963SMatthew Dillon 	enable = (ieee80211_alq != NULL);
106*085ff963SMatthew Dillon 	error = sysctl_handle_int(oidp, &enable, 0, req);
107*085ff963SMatthew Dillon 	if (error || !req->newptr)
108*085ff963SMatthew Dillon 		return (error);
109*085ff963SMatthew Dillon 	else
110*085ff963SMatthew Dillon 		return (ieee80211_alq_setlogging(enable));
111*085ff963SMatthew Dillon }
112*085ff963SMatthew Dillon 
113*085ff963SMatthew Dillon SYSCTL_PROC(_net_wlan, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
114*085ff963SMatthew Dillon 	0, 0, sysctl_ieee80211_alq_log, "I", "Enable net80211 alq logging");
115*085ff963SMatthew Dillon SYSCTL_INT(_net_wlan, OID_AUTO, alq_size, CTLFLAG_RW,
116*085ff963SMatthew Dillon 	&ieee80211_alq_qsize, 0, "In-memory log size (#records)");
117*085ff963SMatthew Dillon SYSCTL_INT(_net_wlan, OID_AUTO, alq_lost, CTLFLAG_RW,
118*085ff963SMatthew Dillon 	&ieee80211_alq_lost, 0, "Debugging operations not logged");
119*085ff963SMatthew Dillon SYSCTL_INT(_net_wlan, OID_AUTO, alq_logged, CTLFLAG_RW,
120*085ff963SMatthew Dillon 	&ieee80211_alq_logged, 0, "Debugging operations logged");
121*085ff963SMatthew Dillon 
122*085ff963SMatthew Dillon static struct ale *
ieee80211_alq_get(void)123*085ff963SMatthew Dillon ieee80211_alq_get(void)
124*085ff963SMatthew Dillon {
125*085ff963SMatthew Dillon 	struct ale *ale;
126*085ff963SMatthew Dillon 
127*085ff963SMatthew Dillon 	ale = alq_get(ieee80211_alq, ALQ_NOWAIT);
128*085ff963SMatthew Dillon 	if (!ale)
129*085ff963SMatthew Dillon 		ieee80211_alq_lost++;
130*085ff963SMatthew Dillon 	else
131*085ff963SMatthew Dillon 		ieee80211_alq_logged++;
132*085ff963SMatthew Dillon 	return ale;
133*085ff963SMatthew Dillon }
134*085ff963SMatthew Dillon 
135*085ff963SMatthew Dillon void
ieee80211_alq_log(struct ieee80211vap * vap,uint8_t op,u_char * p,int l)136*085ff963SMatthew Dillon ieee80211_alq_log(struct ieee80211vap *vap, uint8_t op, u_char *p, int l)
137*085ff963SMatthew Dillon {
138*085ff963SMatthew Dillon 	struct ale *ale;
139*085ff963SMatthew Dillon 	struct ieee80211_alq_rec *r;
140*085ff963SMatthew Dillon 
141*085ff963SMatthew Dillon 	if (ieee80211_alq == NULL)
142*085ff963SMatthew Dillon 		return;
143*085ff963SMatthew Dillon 
144*085ff963SMatthew Dillon 	ale = ieee80211_alq_get();
145*085ff963SMatthew Dillon 	if (! ale)
146*085ff963SMatthew Dillon 		return;
147*085ff963SMatthew Dillon 
148*085ff963SMatthew Dillon 	r = (struct ieee80211_alq_rec *) ale->ae_data;
149*085ff963SMatthew Dillon 	r->r_timestamp = htonl(ticks);
150*085ff963SMatthew Dillon 	r->r_version = 1;
151*085ff963SMatthew Dillon 	r->r_wlan = htons(vap->iv_ifp->if_dunit);
152*085ff963SMatthew Dillon 	r->r_op = op;
153*085ff963SMatthew Dillon 	r->r_threadid = htonl((uint32_t) curthread->td_tid);
154*085ff963SMatthew Dillon 	memcpy(&r->r_payload, p, MIN(l, sizeof(r->r_payload)));
155*085ff963SMatthew Dillon 	alq_post(ieee80211_alq, ale);
156*085ff963SMatthew Dillon }
157