Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src-draft/trunk]: src/sys/net80211 Defer management input via a ifqueue.
details: https://anonhg.NetBSD.org/src-all/rev/519a40d07128
branches: trunk
changeset: 371178:519a40d07128
user: Martin Husemann <martin%NetBSD.org@localhost>
date: Tue Sep 20 20:29:23 2022 +0200
description:
Defer management input via a ifqueue.
Introduce a helper function ieee80211_rx_enqueue() that handles all
the details of incoming traffic and can be safely called by
drivers with locks held.
diffstat:
sys/net80211/ieee80211.c | 12 ++++
sys/net80211/ieee80211_netbsd.c | 120 ++++++++++++++++++++++++++++++++++++++++
sys/net80211/ieee80211_netbsd.h | 10 +++
3 files changed, 142 insertions(+), 0 deletions(-)
diffs (214 lines):
diff -r d5f834ebb3b6 -r 519a40d07128 sys/net80211/ieee80211.c
--- a/sys/net80211/ieee80211.c Tue Sep 20 20:26:54 2022 +0200
+++ b/sys/net80211/ieee80211.c Tue Sep 20 20:29:23 2022 +0200
@@ -435,6 +435,7 @@
if (workqueue_create(&ic->ic_tq, name,
ieee80211_runwork, ic, PRI_SOFTNET, IPL_NET, WQ_MPSAFE))
panic("net80211 workqueue not created");
+ ieee80211_init_mgmt_wqueue();
#endif
/*
@@ -483,6 +484,9 @@
ieee80211_ifdetach(struct ieee80211com *ic)
{
struct ieee80211vap *vap;
+#if __NetBSD__
+ bool last_vap;
+#endif
/*
* We use this as an indicator that ifattach never had a chance to be
@@ -495,6 +499,9 @@
mtx_lock(&ic_list_mtx);
LIST_REMOVE(ic, ic_next);
+#if __NetBSD__
+ last_vap = LIST_EMPTY(&ic_head);
+#endif
mtx_unlock(&ic_list_mtx);
taskqueue_drain(ic->ic_tq, &ic->ic_restart_task);
@@ -532,6 +539,11 @@
taskqueue_free(ic->ic_tq);
IEEE80211_TX_LOCK_DESTROY(ic);
IEEE80211_LOCK_DESTROY(ic);
+
+#if __NetBSD__
+ if (last_vap)
+ ieee80211_deinit_mgmt_wqueue();
+#endif
}
struct ieee80211com *
diff -r d5f834ebb3b6 -r 519a40d07128 sys/net80211/ieee80211_netbsd.c
--- a/sys/net80211/ieee80211_netbsd.c Tue Sep 20 20:26:54 2022 +0200
+++ b/sys/net80211/ieee80211_netbsd.c Tue Sep 20 20:29:23 2022 +0200
@@ -86,9 +86,14 @@
IF_CLONE_WITH_ARGS_INITIALIZER(wlanname,
wlan_clone_create, wlan_clone_destroy);
+static void ieee80211_rx_mgmt_cb(void *, int);
+static struct ifqueue ieee80211_rx_mgmt;
+static struct task ieee80211_mgmt_input;
+
int
ieee80211_init0(void)
{
+
return 0;
}
@@ -1566,6 +1571,7 @@
void
ieee80211_if_attach(struct ifnet *ifp, const uint8_t *lla)
{
+
ifp->if_type = IFT_ETHER;
ifp->if_hdrlen = ETHER_HDR_LEN;
ifp->if_dlt = DLT_EN10MB;
@@ -1581,3 +1587,117 @@
ifp->if_broadcastaddr = etherbroadcastaddr;
bpf_attach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
}
+
+/*
+ * If we have not yet initialized the ifq/task for global defered
+ * processing of mgmt/ctrl frames, do it now.
+ */
+void
+ieee80211_init_mgmt_wqueue(void)
+{
+ if (ieee80211_rx_mgmt.ifq_maxlen != 0)
+ return; /* been here before */
+
+ IFQ_SET_MAXLEN(&ieee80211_rx_mgmt, IFQ_MAXLEN);
+ IFQ_LOCK_INIT(&ieee80211_rx_mgmt);
+ TASK_INIT(&ieee80211_mgmt_input, 0, ieee80211_rx_mgmt_cb, 0);
+}
+
+/*
+ * The last VAP is gone, free taskquee and IFQ resources
+ */
+void
+ieee80211_deinit_mgmt_wqueue(void)
+{
+
+ IFQ_LOCK_DESTROY(&ieee80211_rx_mgmt);
+ TASK_DESTROY(&ieee80211_mgmt_input);
+ memset(&ieee80211_rx_mgmt, 0, sizeof ieee80211_rx_mgmt);
+ memset(&ieee80211_mgmt_input, 0, sizeof ieee80211_mgmt_input);
+}
+
+/*
+ * utility function to handle RX mbuf:
+ * - classifies input and uses proper API to pass it further up the stack
+ * - may queue and process input later in thread context, if input needs
+ * more work than we are allowed in softint context
+ */
+void
+ieee80211_rx_enqueue(struct ieee80211com *ic, struct mbuf *m, int rssi)
+{
+ struct ieee80211_frame *wh;
+ struct ieee80211_node *ni;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
+
+ if (IEEE80211_IS_DATA(wh)) {
+ /*
+ * Just pass it up, it will be enqueued on the VAPs ifqueue
+ */
+ if (ni != NULL) {
+ if (ni->ni_vap == NULL) {
+ ieee80211_free_node(ni);
+ return;
+ }
+ ieee80211_input(ni, m, rssi, 0);
+ ieee80211_free_node(ni);
+ } else {
+ /* XXX will this ever happen? */
+ ieee80211_input_all(ic, m, rssi, 0);
+ }
+ } else {
+ /*
+ * We might need to take "heavy" locks during
+ * further processing (like the IC lock), and can
+ * not do this from softint or callout context.
+ */
+ M_SETCTX(m, ic);
+ m_append(m, sizeof(rssi), &rssi);
+ IF_ENQUEUE(&ieee80211_rx_mgmt, m);
+ taskqueue_enqueue(ic->ic_tq, &ieee80211_mgmt_input);
+ }
+}
+
+static void
+ieee80211_rx_mgmt_cb(void *a0, int a1)
+{
+ struct mbuf *m, *ml;
+ struct ieee80211com *ic;
+ struct ieee80211_node *ni;
+ struct ieee80211_frame *wh;
+ int rssi;
+
+ for (;;) {
+ IF_DEQUEUE(&ieee80211_rx_mgmt, m);
+ if (!m)
+ return;
+ ic = M_GETCTX(m, struct ieee80211com *);
+ M_SETCTX(m, NULL);
+ /*
+ * usually this will be a single mbuf
+ */
+ for (ml = m; ml->m_next != NULL; ml = ml->m_next)
+ ;
+ memcpy(&rssi, mtod(m, char *) + m->m_len - sizeof(rssi),
+ sizeof(rssi));
+ m_adj(m, -(ssize_t)sizeof(rssi));
+
+
+ wh = mtod(m, struct ieee80211_frame *);
+ ni = ieee80211_find_rxnode(ic,
+ (struct ieee80211_frame_min *)wh);
+
+ if (ni != NULL) {
+ if (ni->ni_vap == NULL) {
+ ieee80211_free_node(ni);
+ return;
+ }
+ ieee80211_input(ni, m, rssi, 0);
+ ieee80211_free_node(ni);
+ } else {
+ ieee80211_input_all(ic, m, rssi, 0);
+ }
+ }
+}
+
diff -r d5f834ebb3b6 -r 519a40d07128 sys/net80211/ieee80211_netbsd.h
--- a/sys/net80211/ieee80211_netbsd.h Tue Sep 20 20:26:54 2022 +0200
+++ b/sys/net80211/ieee80211_netbsd.h Tue Sep 20 20:29:23 2022 +0200
@@ -135,6 +135,8 @@
struct timeout_task *timeout_task);
int ieee80211_clone_attach(void);
void ieee80211_if_attach(struct ifnet *ifp, const uint8_t *lla);
+void ieee80211_init_mgmt_wqueue(void);
+void ieee80211_deinit_mgmt_wqueue(void);
#define TASK_INIT(var, pri, func, arg) do { \
@@ -1121,6 +1123,14 @@
#define ieee80211_get_qos(WH) \
(((struct ieee80211_qosframe *)(void*)(WH))->i_qos[0])
+/*
+ * utility function to handle RX mbuf:
+ * - classifies input and uses proper API to pass it further up the stack
+ * - may queue and process input later in thread context, if input needs
+ * more work than we are allowed in softint context
+ */
+void ieee80211_rx_enqueue(struct ieee80211com *ic, struct mbuf *m, int rssi);
+
#endif /* _KERNEL */
#endif /* _NET80211_IEEE80211_NETBSD_H_ */
Home |
Main Index |
Thread Index |
Old Index