upper layer(s).
This eliminates the if_snd queue from net80211. Yay!
This unfortunately has a few side effects:
* It breaks ALTQ to net80211 for now - sorry everyone, but fixing
parallelism and eliminating the if_snd queue is more important
than supporting this broken traffic scheduling model. :-)
* There's no VAP and IC flush methods just yet - I think I'll add
some NULL methods for now just as placeholders.
* It reduces throughput a little because now net80211 will drop packets
rather than buffer them if the driver doesn't do its own buffering.
This will be addressed in the future as I implement per-node software
queues.
Tested:
* ath(4) and iwn(4) in STA operation
the normal and the mesh transmit paths can use.
The API is a bit horrible because it both consumes the mbuf and frees
the node reference regardless of whether it succeeds or not.
It's a hold-over from how the code behaves; it'd be nice to have it
not free the node reference / mbuf if TX fails and let the caller
decide what to do.
* Add 802.11n 2ghz and 5ghz tables, including legacy rates and up to
MCS23 rates (3x3.)
* Populate the rate code -> rate index lookup table with MCS _and_
normal rates, but _not_ the basic rate flag. Since the basic rate flag
is the same as the MCS flag, we can only use one.
* Introduce some accessor inlines that do PLCP and rate table lookup/access
and enforce that it doesn't set the basic rate bit. They're not
designed for MCS rates, so it will panic.
* Start converting drivers that use the rate table stuff to use the
accessor inlines and strip the basic flag.
* Teach AMRR about basic 11n - it's still as crap for MCS as it is
being used by iwn, so it's not a step _backwardS_.
* Convert iwn over to accept 11n MCS rates rather than 'translate' legacy
to MCS rates. It doesn't use a lookup table any longer; instead it's a
function which takes the current node (for HT parameters) and the
rate code, and returns the hardware PLCP code to use.
Tested:
* ath - it's a no-op, and it works that way
* iwn - both 11n and non-11n
The "find node" function call will increase the node reference anyway;
so there's no reason to hold the node table lock during the MLME change.
The only reason I could think of is to stop overlapping mlme ioctls
from causing issues, but this should be fixed a different way.
This fixes a whole class of LORs that creep up when nodes are being
timed out or removed by hostapd.
Tested:
* AR5416, hostap, with nodes coming and going. No LORs or stability
issues were observed.
When creating fragment frames, the header length should honour the
DATAPAD flag.
This fixes the fragments that are queued to the ath(4) driver but it
doesn't yet fix fragment transmission. That requires further changes
to the ath(4) transmit path. Well, strictly speaking, it requires
further changes to _all_ wifi driver transmit paths, but this is at least
a start.
Tested:
* AR5416, STA mode, w/ fragthreshold set to 256.
before using said node.
The "blessed" way here is to take a node reference before referencing
anything inside the node, otherwise the node can be freed between
the time the pointer is copied/dereferenced and the time the node contents
are used.
This mirrors fixes that I've done elsewhere in the net80211/driver
stack.
PR: kern/178470
the given node.
This takes into account the per-node cap, the ic cap and the
per-channel regulatory caps.
This is designed to replace references to ni_txpower in various net80211
drivers - ni_txpower doesn't necessarily reflect the actual cap for
the given node (eg if the node has the default value of 50dBm (100) and
the administrator has manually configured a lower TX power.)
This patchset implements a new TX lock, covering both the per-VAP (and
thus per-node) TX locking and the serialisation through to the underlying
physical device.
This implements the hard requirement that frames to the underlying physical
device are scheduled to the underlying device in the same order that they
are processed at the VAP layer. This includes adding extra encapsulation
state (such as sequence numbers and CCMP IV numbers.) Any order mismatch
here will result in dropped packets at the receiver.
There are multiple transmit contexts from the upper protocol layers as well
as the "raw" interface via the management and BPF transmit paths.
All of these need to be correctly serialised or bad behaviour will result
under load.
The specifics:
* add a new TX IC lock - it will eventually just be used for serialisation
to the underlying physical device but for now it's used for both the
VAP encapsulation/serialisation and the physical device dispatch.
This lock is specifically non-recursive.
* Methodize the parent transmit, vap transmit and ic_raw_xmit function
pointers; use lock assertions in the parent/vap transmit routines.
* Add a lock assertion in ieee80211_encap() - the TX lock must be held
here to guarantee sensible behaviour.
* Refactor out the packet sending code from ieee80211_start() - now
ieee80211_start() is just a loop over the ifnet queue and it dispatches
each VAP packet send through ieee80211_start_pkt().
Yes, I will likely rename ieee80211_start_pkt() to something that
better reflects its status as a VAP packet transmit path. More on
that later.
* Add locking around the management and BAR TX sending - to ensure that
encapsulation and TX are done hand-in-hand.
* Add locking in the mesh code - again, to ensure that encapsulation
and mesh transmit are done hand-in-hand.
* Add locking around the power save queue and ageq handling, when
dispatching to the parent interface.
* Add locking around the WDS handoff.
* Add a note in the mesh dispatch code that the TX path needs to be
re-thought-out - right now it's doing a direct parent device transmit
rather than going via the vap layer. It may "work", but it's likely
incorrect (as it bypasses any possible per-node power save and
aggregation handling.)
Why not a per-VAP or per-node lock?
Because in order to ensure per-VAP ordering, we'd have to hold the
VAP lock across parent->if_transmit(). There are a few problems
with this:
* There's some state being setup during each driver transmit - specifically,
the encryption encap / CCMP IV setup. That should eventually be dragged
back into the encapsulation phase but for now it lives in the driver TX path.
This should be locked.
* Two drivers (ath, iwn) re-use the node->ni_txseqs array in order to
allocate sequence numbers when doing transmit aggregation. This should
also be locked.
* Drivers may have multiple frames queued already - so when one calls
if_transmit(), it may end up dispatching multiple frames for different
VAPs/nodes, each needing a different lock when handling that particular
end destination.
So to be "correct" locking-wise, we'd end up needing to grab a VAP or
node lock inside the driver TX path when setting up crypto / AMPDU sequence
numbers, and we may already _have_ a TX lock held - mostly for the same
destination vap/node, but sometimes it'll be for others. That could lead
to LORs and thus deadlocks.
So for now, I'm sticking with an IC TX lock. It has the advantage of
papering over the above and it also has the added advantage that I can
assert that it's being held when doing a parent device transmit.
I'll look at splitting the locks out a bit more later on.
General outstanding net80211 TX path issues / TODO:
* Look into separating out the VAP serialisation and the IC handoff.
It's going to be tricky as parent->if_transmit() doesn't give me the
opportunity to split queuing from driver dispatch. See above.
* Work with monthadar to fix up the mesh transmit path so it doesn't go via
the parent interface when retransmitting frames.
* Push the encryption handling back into the driver, if it's at all
architectually sane to do so. I know it's possible - it's what mac80211
in Linux does.
* Make ieee80211_raw_xmit() queue a frame into VAP or parent queue rather
than doing a short-cut direct into the driver. There are QoS issues
here - you do want your management frames to be encapsulated and pushed
onto the stack sooner than the (large, bursty) amount of data frames
that are queued. But there has to be a saner way to do this.
* Fragments are still broken - drivers need to be upgraded to an if_transmit()
implementation and then fragmentation handling needs to be properly fixed.
Tested:
* STA - AR5416, AR9280, Intel 5300 abgn wifi
* Hostap - AR5416, AR9160, AR9280
* Mesh - some testing by monthadar@, more to come.
* The following bit flags where incroccetly defined:
o Mesh Control Present
o Mesh Power Save Level
o RSPI
This is now corrected according to Table 8.4 as per IEEE 802.11 2012;
Approved by: adrian (mentor)
since the former is defined everywhere. This cuts off some code not
necessary on non strict aligment arches.
Reviewed by: adrian
Sponsored by: Nginx, Inc.
* Add the superg.h header to allow ieee80211_check_ff() to work
* Since the assert stuff creates assertions based on line numbers and there
was a conflict, just nudge things down a bit.
* Added hwmp_update_transmitter function that checks if the metric
to the transmitter have improved. If old FI is invalid or metric
is larger the FI to the transmitter is updated occurdingly.
This is a recommendation from the 802.11 2012 standard, table 13-9;
Approved by: adrian (mentor)
* When calling ieee80211_mesh_rt_flush_peer, the rt->rt_dest argument
should not be passed because it can get freed before invalidating
the other routes that depends on it to compare with next_hop.
Use PERR_DADDR(i) instead;
Approved by: adrian (mentor)
* The standard is unclear about what should happen in case a mesh STA (not
marked as a mesh gate) recevies a PREQ for a destination that is marked
as proxy. Solution for now is not to do intermediate reply at all, and
let the PREQ reach the mesh gate;
Approved by: adrian (mentor)
* Original PREP frame is transmitted only by the target mesh STA or the
mesh STA that is the proxy target;
* Fixed so that metric value is not over written incorrectly in
hwmp_recv_preq for when replying back with a PREP;
Approved by: adrian (mentor)
This is a code re-write. ic->raw_xmit need a pointer to ieee80211_node
for the destination node (da). I have reorganized the code so that
a pointer to the da node is searched for in the end & in one place.
* Make mesh_find_txnode public to be used by HWMP, renamed to
ieee80211_mesh_finx_txnode;
* changed the argument from ieee80211_node to ieee80211vap for all
hwmp_send_* functions;
* removed the 'sa' argument from hwmp_send_* functions as all HWMP frames
have the source address equal to vap->iv_myaddr;
* Modified hwmp_send_action so that if da is MULTCAST ni=vap->iv_bss
otherwise we called ieee80211_mesh_find_txnode. Also no need to hold
a reference in this functions if da is not MULTICAST as by finding the
node it became referenced in ieee80211_find_txnode;
Approved by: adrian (mentor)
* Modified mesh_find_txnode to be able to handle proxy marked entries by
recursively calling itself to find the txnode towards the active mesh gate;
* Mesh Gate: Added a new function that transmits data frames
similar to ieee80211_start;
* Modified ieee80211_mesh_forward_to_gates so that:
+ Frames are duplicated and sent to each valid Mesh Gate;
+ Route is marked invalid before return of function, this is
because we dont know yet which Mesh Gate is we will use;
Approved by: adrian (mentor)
* Send frames that have no path to a known valid Mesh Gate;
* Added the function ieee80211_mesh_forward_to_gates that sends the frame
to the first found Mesh Gate in the forwarding information;
* If we try to discover again while we are discovering queue frame,
the discovery callout will send the frames either to mesh gates
or discards them silently;
* Queue frame also if we try to discover to frequently;
Approved by: adrian (mentor)
* Add function ieee80211_mesh_mark_gate in ieee80211_mesh.h;
* When received a proactive PREQ or RANN with corresponding mesh gate
flag set, create a new entry in the known mesh gate list;
Approved by: adrian (mentor)
* Modified mesh_recv_action_meshgate to do following:
+ if mesh STA already knows the mesh gate of the recevied GANN frame
+ if mesh gate is know, check seq number according to 802.11 standard
+ if mesh gate is not know, add it to the list of known mesh gates
+ if forwarding is enabled and ttl >= 1 then propagate the GANN frame;
* Declare a new malloc type M_80211_MESH_GT_RT;
* Declare a struct to store GANN information, ieee80211_mesh_gate_route. And
add it as a TAILQ list to ieee80211_mesh_state;
Approved by: adrian (mentor)
A Mesh Gate should transmit a Mesh Action frame containing
ieee80211_meshgann_ie as its only information element periodically
every ieee80211_mesh_gateint ms. Unless the mesh gate is also configure
as a ROOT, then these frames should not be send.
This is according to 802.11 2012 standard;
* Introduce new SYSCTL net.wlan.mesh.gateint, with 10s default;
* Add two new functions mesh_gatemode_setup and mesh_gatemode_cb. This
is similar to how HWMP setups up a callout;
* Add two new action handlers mesh_recv_action_meshgate and
mesh_send_action_meshgate;
* Added ieee80211_add_meshgate to ieee80211_mesh.h;
* Modified mesh_send_action to look similar to hwmp_send_action. This is
because we need to send out broadcast management frames.
* Introduced a new flag for mesh state IEEE80211_MESHFLAGS_ROOT. This flag
is now set by HWMP code when a mesh STA is configured as a ROOT. This
is then checked by mesh_gatemode_cb before scheduling a new callout;
* Added to new field to ieee80211_mesh_state:
+ struct callout ms_gatetimer
+ ieee80211_mesh_seq ms_gateseq;
Approved by: adrian (mentor)
when not peered.
* Modified ieee80211_recv_action to check if neighbour is peered for
IEEE80211_ACTION_CAT_MESH frames, if not frame is discarded. This is
according to IEEE802.11 2012 standard;
* Removed duplicate checks in each hwmp_recv_* handlers because HWMP
is a subtype of mesh action;
Approved by: adrian (mentor)
* Removed meshlm_send_action and hwmp_send_action. Introduced one common
for all Mesh Action frames meshaction_send_action. According to 802.11
standard Link Metric and HWMP are all under Mesh Action category;
* Did similar changes to recv_action part;
* The size of meshaction_*_action is set to 12. This is to make room for
the rest of Mesh Action category subtypes;
Approved by: adrian (mentor)
* Change all field prefix from pann_ to gann_;
* Added IEEE80211_MESHGANN_BASE_SZ macro to be used in the length field
of a GANN frame according to 802.11 standard;
* Changed gann_seq field type to uint32_t;
* Added a Gate Announcement interval field according to
IEEE802.11 2012 standard;
* Added IEEE80211_MESHRT_FLAGS_GATE as flag bit to ieee80211_mesh_route;
* Added IEEE80211_MESHRT_FLAGS_GATE as flag bit to ieee80211req_mesh_route;
Approved by: adrian (mentor)
* An HWMP PERR should be accepted even if path is valid. Because
we check if we recevied it from a neighbour that we use as a next hop;
Approved by: adrian (mentor)
* A bug occurs while in discovery mode which leaves a path marked with
both Discover and Valid flag. This happens when receiving/sending
PREQ and PREP in a particular order. Solution is to assign the Valid bit
instead of oring it;
Approved by: adrian (mentor)
This problem happens when using ACL policy to filter mesh STA
but two nodes have different policy. Then one of them will try to
peer all the time. This can also help if for any reason one of the
peering mesh STA have problems sending/receiving peer frames.
* Modified struct ieee80211_node to include two new fields:
+ struct callout ni_mlhtimer /* link mesh backoff timer */
+ uint8_t ni_mlhcnt /* link mesh holding counter */
* Added two new sysctl (check sysctl -d for more info):
+ net.wlan.mesh.backofftimeout=5000
+ net.wlan.mesh.maxholding=2;
* When receiving a beacon and we are in IEEE80211_NODE_MESH_IDLE
check if ni_mlhcnt >= ieee80211_mesh_maxholding, if so do not do anything;
* In mesh_peer_timeout_cb when transitioning from IEEE80211_NODE_MESH_HOLDING
to IEEE80211_NODE_MESH_IDLE increment ni_mlhcnt, and eventually start
ieee80211_mesh_backofftimeout;
Approved by: adrian (mentor)
* Add HTINFO field decoding to ieee80211_ies_expand() - it's likely not
100% correct as it's not looking at the draft 11n HTINFO location,
but I don't think anyone will care.
* When doing an IBSS join make sure the 11n channel configuration
is used - otherwise the 11a/11bg channel will be used
and there won't be any chance for an upgrade to 11n.
* When creating an IBSS network, ensure the channel is updated to an
11n channel so other 11n nodes can see it and speak to it with MCS
rates.
* Add a bit of code that's disabled for now which handles the HT
field updating. This won't work out very well with lots of adhoc
nodes as we'd end up ping-ponging between the HT configuration for
each node. Instead, we should likely only pay attention to the
"master" node we initially associated against and then ensure we
propagate that information forward in our subsequent beacons. However,
due to the nature of IBSS (ie, there's no specific "master" node in
the specification) it's unclear which node we should lift the HT
parameters from.
So for now this assumes the HT parameters are squirreled away in the
initial beacon/probe response.
So there's some trickiness here.
With ap/sta pairing, the probe response just populates a legacy node
and the association request/response is what is used for negotiation
11n-ness (and upgrading things as needed.)
With ibss networks, the pairing is done with probe request/response,
with discovery being done by creating nodes when new beacons in the
IBSS / BSSID are heard. There's no assoc request/response frames going on.
So the trick here has been to figure out where to upgrade things.
I don't like how I just taught ieee80211_sta_join() to "speak" HT -
I'd rather there be an upgrade path when an IBSS node joins and there
are HT parameters present. Once I've done that, I'll kill this
HT special casing that's going on in ieee80211_sta_join().
Tested:
* AR9280, AR5416, AR5212 - basic iperf and ping interoperability tests
whilst in a non-encrypted adhoc network.
TODO:
* Fix up the HT upgrade path for IBSS nodes rather than adding code
in ieee80211_sta_join(), then remove my code from there.
* When associating, there's a concept of a "master" node in the IBSS
which is the node you first joined the network through. It's possible
the correct thing to do is to listen to HT updates and configure WME
parameters from that node. However, once that node goes away, which
node(s) should be listened to for configuration changes?
For things like HT channel width, it's likely going to be ok to
just associate as HT40 and then use the per-neighbor rate control
and HTINFO/HTCAP fields to figure out which rates and configuration
to speak. Ie, for a 20MHz 11n node, just speak 20MHz rates to
it. It shouldn't "change", like what goes on in AP/STA configurations.
save queue code.
Instead, use if_transmit() directly - and handle the cases where frame
transmission fails.
I don't necessarily like this and I think at this point the M_ENCAP check,
node freeing upon fail and the actual if_transmit() call should be done
in methods in ieee80211_freebsd.c, but I digress slightly..
This removes one of the last few uses of if_start() and the ifnet
if_snd queue. The last major offender is ieee80211_output.c, where
ieee80211_start() implements if_start() and uses the ifnet queue
directly.
(There's a couple of gotchas here, where the if_start pointer is
compared to ieee80211_start(), but that's a later problem.)
If the data frame transmission failures, it may have a node reference
that needs cleaning up.
If the frame is marked as M_ENCAP then it should treat recvif as a node
reference and clear it.
Now - since the mbuf has been freed by calling if_transmit() (even on
failure), the mbuf has to be treated as invalid. Hence why the ifp is
used.
If if_transmit() fails, the node ref may need freeing.
This is based on the same logic used by the ageq, which the mesh code
(re) uses for frames which need to be staged before transmitting.
It also does the same thing - if M_ENCAP is set on the mbuf, it treats
the recvif pointer as a node reference and derefs it.
processing. For if_transmit() style hardware drivers (which none publicly
exist yet, for wireless) they will need to still implement if_start()
but only to re-start the TX queue.
an IBSS VAP to RUN.
An 11n IBSS was beaconing HTINFO/HTCAP IE's that didn't have any HT
information setup (like the HT TX/RX MCS bitmask.)
Tested:
* AR9280, IBSS - both a statically setup channel and a scanned channel
PR: kern/172955
parameters in IBSSes.
IBSS was just being plainly ignored here even though aggressive mode
was 'on'.
This still doesn't fix the "why are the WME parameters reset upon
interface down/up" issue.
PR: kern/165969
is totally wrong.
If we parse the WME IE here, we'll be constantly updating the WME
configuration from each WME enabled IBSS node we see.
There's a separate issue where the WME configuration is blanked out
when the interface is brought up; the WME parameters aren't "sticky."
Also, ieee80211_init_neighbor() parses the ath IE, so doing it here
isn't required.
Sorry about the noise.
PR: kern/165969
The Adhoc support wasn't parsing and handling the ath specific and WME
IEs, thus the atheros vendor support and WME TXOP parameters aren't being
copied from the peer.
It copies the WME parameters from whichever adhoc node it decides to
associate to, rather than just having them be statically configured
per adhoc node. This may or may not be exactly "right", but it's certainly
going to be more convienent for people - they just have to ensure their
adhoc nodes are setup with correct WME parameters.
Since WME parameters aren't per-node but are configured on hardware TX
queues, if some nodes support WME and some don't - or perhaps, have
different WME parameters - things will get quite quirky.
So ensure that you configure your adhoc nodes with the same WME
parameters.
Secondly - the Atheros Vendor IE is parsed and operated on per-node, so
this should work out ok between nodes that do and don't do Atheros
extensions. Once you see a becaon from that node and you setup the
association state, it _should_ parse things correctly.
TODO:
* I do need to ensure that both adhoc setup paths are correctly updating
the IE stuff. Ie, if the adhoc node is created by a data frame instead
of a beacon frame, it'll come up with no WME/ath IE config. The next
beacon frame that it receives from that node will update the state.
I just need to sit down and better understand how that's suppose to
work in IBSS mode.
Tested:
* AR5416 <-> AR9280 - fast frames and the WME configuration both popped
up. (This is with a local HAL patch that enables the fast frames
capability on the AR5416 chipsets.)
PR: kern/165969
The stageqdepth (global, over all staging queues) was being kept
incorrectly. It was being incremented whenever things were added,
but only decremented during a flush. During active fast frames activity
it wasn't being decremented, resulting in it always having a non-zero
value during normal fast-frames operation.
It was only used when checking if the aging queue should be checked;
we may as well just defer to each of those staging queue counters (which
look correct, thankfully.)
Whilst I'm here, add locking assertions in the staging queue add/remove
functions. The current crash shows that the staging queue has one frame,
but only has a tail pointer set (the head pointer being set to NULL.)
I'd like to grab a few more crashes where these locking assertions are
in place so I can narrow down the issue between "somehow locking is
messed up and things are racy" and "the stage queue head/tail pointer
manipulation logic is subtly wrong."
Tested:
* AR5416 STA, AR5413 AP; with FastFrames enabled in the AR5416 HAL.
PR: kern/174283
pointers and leave the stage queue flush routine to just do nothing
(since both head and tail here will be NULL.)
This should quieten the "stageq empty" panic where the stageq itself
is empty, but it won't fix the second KASSERT() here "staging queue empty"
as that's likely a different underlying problem.
PR: kern/174283
The XC900M acts as a Ubiquiti XR9 (and I _think_ SR9) by default;
it uses the same 900MHz<->2.4GHz downconverter mapping.
However it has an alternative frequency mapping which squeezes in a couple
more half/quarter rate channels. Since the default HAL doesn't support
fractional tuning (sub-1MHz) in 2.4GHz mode on the AR5413/AR5414, they
implement it using a jumper.
Datasheet: http://www.xagyl.com/download/XC900M_Datasheet.pdf
Thankyou to Xagyl Communications for the XC900M NICs and Edgar Martinez
for organising the donation.
Tested:
* XC900M <-> XC900M
* Ubiquiti XR9 <-> XC900M
TODO:
* Test against SR9 and GZ901 if possible (the IEEE channel<->frequency
mapping may not match up, thanks to the slightly different channels
involved)
There are some people who use the -HEAD net80211 and wireless drivers
on earlier FreeBSD versions in order to get the updated 802.11n support.
The previous if_clone API changes broke this.
net80211 devices and vaps.
* vnet sets vnet0 during kldload and device probe/attach, but not for
the hotplug event. Thus, plugging in a NIC causes things to panic.
So, add a CURVNET_SET(vnet0) for now during the attach phase, until
the hotplug code is taught to set CURVNET_SET(vnet0).
* there's also no implied detach vnet context - so teach the detach
path about ifp->if_vnet.
* When creating/deleting vaps, also set the vnet context appropriately.
These can be done at any time.
Now, the problems!
* ieee80211.c is supposed to be OS-portable code, with no OS-specific stuff
like vnet. That should be fixed.
* When the device hotplug code gets taught about CURVNET_SET(vnet0), the
device vnet set can go away; but the VAP vnet set still needs to be there.
* .. and there still is the question about potentially adding an implied
CURVNET_SET(ifp->if_vnet) on if_free(), since any/all devices may end up
being detached by a hotplug event in today's world. That's going to be
a topic of a subsequent commit.
now use function calls:
if_clone_simple()
if_clone_advanced()
to initialize a cloner, instead of macros that initialize if_clone
structure.
Discussed with: brooks, bz, 1 year ago
This turns ieee80211_node_pwrsave(), ieee80211_sta_pwrsave() and
ieee80211_recv_pspoll() into methods.
The intent is to let drivers override these and tie into the power save
management pathway.
For ath(4), this is the beginning of forcing a node software queue to
stop and start as needed, as well as supporting "leaking" single frames
from the software queue to the hardware.
Right now, ieee80211_recv_pspoll() will attempt to transmit a single frame
to the hardware (whether it be a data frame on the power-save queue or
a NULL data frame) but the driver may have hardware/software queued frames
queued up. This initial work is an attempt at providing the hooks required
to implement correct behaviour.
Allowing ieee80211_node_pwrsave() to be overridden allows the ath(4)
driver to pause and unpause the entire software queue for a given node.
It doesn't make sense to transmit anything whilst the node is asleep.
Please note that there are other corner cases to correctly handle -
specifically, setting the MORE data bit correctly on frames to a station,
as well as keeping the TIM updated. Those particular issues can be
addressed later.
iterate lock.
This causes LORs and deadlocks as some code paths will have the com lock
held when calling ieee80211_iterate_nodes().
Here, the comlock isn't held during the node table and node iteration
locks; and the callback isn't called with any (extra) lock held.
PR: kern/170098
Submitted by: moonlightakkiy@yahoo.ca
MFC after: 4 weeks
* Earlier we compared two not equal metrics, one was what we recevied
in the 'new PREQ' while the other was what we already have saved which
was 'old PREQ' + link metric for the last hop;
* Fixed by adding 'new PREQ' + link metric for the last hop in a
temporary variable;
For description of the test scripts refer to projects/net80211_testsuite/wtap.
* Test 007 showed a bug in intermediate PREP for a proxy entry. Resolved;
* Test 002 showed a bug in the Addressing Mode flag for a PREQ. Resolved;
* qos[1] subfield is never assigned a value before this statement.
qos[1] can potentially be OR:ed with garbage. Make it an assignment instead;
* Remove brackets around if statement;
Approved by: adrian
bitmaps that may occur.
The way this works is:
* the beginning of the radiotap frame has a 32 bit "radiotap" namespace
bitmap;
* if the vendor bitmap bit is set, then the next bitmap will be interpreted
as a vendor bitmap;
* this can keep going on and on (ie, more vendor and radiotap namespace
bitmaps can be added) until the last bitmap with no "more bitmaps" set.
Now, the radiotap code gets its grubby fingers into the supplied
radiotap rx/tx buffer and replaces the channel configuration
for each frame. I don't know why it's not up to the drivers themselves
to do this, but I digress. So, if a vendor bitmap (or two, etc) exists,
the offset calculations will be all completely wrong.
This particular patch introduces ieee80211_radiotap_attachv(), which
includes the number of vendor bitmaps (well, any other bitmaps, vendor
or otherwise) between the end of the bitmap/header and the start of the
actual radiotap field entries. This makes the radiotap calculations
"right", so it correctly calculates where to overwrite the channel
configuration.
The long term fix is to go through and make each driver update the channel
configuration, as some of the fields are already being updated.
That, however, is a longer term fix that will need each driver fixed.
I leave that as an exercise to someone in the future.
* If the first call succeeded but failed to transmit, a timer would
reschedule it via bar_timeout(). Unfortunately bar_timeout() didn't
check the return value from the ieee80211_send_bar() reattempt and
if that failed (eg the driver ic_raw_xmit() failed), it would never
re-arm the timer.
* If BARPEND is cleared (which ieee80211_send_bar() will do if it can't
TX), then re-arming the timer isn't enough - once bar_timeout() occurs,
it'll see BARPEND is 0 and not run through the rest of the routine.
So when rearming the timer, also set that flag.
* If the TX wasn't occuring, bar_tx_complete() wouldn't be called and the
driver callback wouldn't be called either. So the driver had no idea
that the BAR TX attempt had failed. In the ath(4) case, TX would stay
paused.
(There's no callback to indicate that BAR TX had failed or not;
only a "BAR TX was attempted". That's a separate, later problem.)
So call the driver callback (ic_bar_response()) before the ADDBA session
is torn down, so it has a chance of being notified that things didn't
quite go to plan.
I've verified that yes, this does suspend traffic for ath(4), retry BAR
TX even if the driver is failing ic_raw_xmit(), and then eventually giving
up and sending a DELBA. I'll address the "out of ath_buf" issue in ath(4)
in a subsequent commit - this commit just fixes the edge case where any
driver is (way) out of internal buffers/descriptors and fails frame TX.
PR: kern/168170
Reviewed by: bschmidt
MFC after: 1 month
* Modified hwmp_recv_preq:
o cleaned up code, removed rootmac variable because preq->origaddr
is the root when we recevie a Proactive PREQ;
o Modified so that a PREP in response of a Proactive PREQ is unicast,
a PREP is ALWAYS unicast;
* Modified hwmp_recv_prep:
o Before we mark a route to be valid we should remove the discovery
flag and then mark it valid in such a way we wont lose the isgate flag;
Approved by: adrian
* Added a new discovery flag IEEE80211_MESHRT_FLAGS_DISCOVER;
* Modified ieee80211_ioctl.h to include IEEE80211_MESHRT_FLAGS_DISCOVER;
* Added hwmp_rediscover_cb, which will be called by a timeout to do
rediscovery if we have not reach max number of preq discovery;
* Modified hwmp_discover to setup a callout for path rediscovery;
* Added to ieee80211req_mesh_route to have a back pointer to ieee80211vap
for the discovery callout context;
* Modified mesh_rt_add_locked arguemnt from ieee80211_mesh_state to
ieee80211vap, this because we have to initialize the above back pointer;
Approved by: adrian
* Renamed IEEE80211_ELEMID_MESHPANN to IEEE80211_ELEMID_MESHGANN according to
amendment;
* Added IEEE80211_IOC_MESH_GATE that controls whether Mesh Gate Announcement
is activated or not;
* Renamed all flags from Portal to Gate in HWMP frames;
* Removed IEEE80211_ACTION_MESHPANN enum cause its part of the Mesh Action
category now as per amendment;
* Renamed IEEE80211_MESHFLAGS_PORTAL to IEEE80211_MESHFLAGS_GATE in
ieee80211_mesh_state flags;
* Modified ieee80211_hwmp.c/ieee80211_mesh.c to use new GATE flags;
Approved by: adrian
* Introduced a new HWMP sysctl, Root Confirmation Interval;
* Added hr_lastrootconf to hwmp_route, is for ratecheck for a specific ROOT;
* We missed reading RANN.interval subfield from a RANN frame before;
* Updated hwmp_recv_rann according to amendment, see comments;
Approved by: adrian
* Added mpp_senderror for Mesh Path Selection protocol;
* Added hwmp_senderror that will send an HWMP PERR according to the
supplied reason code;
* Call mpp_senderror when deleting a route with correct reason code
for whether the route is marked proxy or not;
* Call mpp_senderror when trying to forward an individually addressed
frame and there is no forwarding information;
Approved by: adrian
* When receiving a Proactive PREQ dont return after processing it but propagate;
* When we propagate we should not enforce ratechecking;
* Added checking for multiple pred ID detection;
* Storing proxy orig address when PREQ is not for us;
Approved by: adrian
* Moved hs_lastpreq to be hr_lastpreq cause this rate check should be per
target mesh STA according to amendment (NB: not applicable for PERR);
* Modified hwmp_send_preq to use two extra arguments for last sent PREQ and
minimum PREQ interval;
* hwmp_send_preq is called with last two arguments equal to NULL when sending
Proactive PREQs cause the call back task enforces the rate check;
Approved by: adrian
* Added assertion in mesh_rt_update;
* Fixed some prep propagation that where multicast, ALL PREPS ARE UNICAST;
* Fixed PREP acceptance criteria;
* Fixed some PREP debug messages;
* HWMP intermediate reply (PREP) should only be sent if we have newer
forwarding infomration (FI) about target;
* Fixed PREP propagation condition and PREP w/ AE handling;
* Ignore PREPs that have unknown originator.
* Removed old code inside PREP that was for proactive path building
to root mesh;
Other errors include:
* use seq number of target and not orig mesh STA;
* Metric is what we have stored in our FI;
* Error in amendment, Hop count is not 0 but equals FI hopcount for target;
Approved by: adrian
* In mesh_recv_indiv_data_to_fwd update route entry for both meshDA and meshSA;
* In mesh_recv_indiv_data_to_me update route entry for meshSA;
* in ieee80211_mesh_rt_update put code so that a proxy entry that is gated
by us (number of hops == 0) is never invalidated;
* Fixed so that we always call ieee80211_mesh_rt_update with lifetime in ms;
Approved by: adrian
* Modified HWMP PREP/PREQ to contain a proxy entry and also changed PREP
frame processing according to amendment as following:
o Fixed PREP to always update/create if acceptance criteria is meet;
o PREQ processing to reply if request is for a proxy entry that is
proxied by us;
o Removed hwmp_discover call from PREQ, because sending a PREP will
build the forward path, and by receving and accepting a PREQ we
have already built the reverse path (non-proactive code);
* Disabled code for pro-active in PREP for now (will make a separate patch for
pro-active HWMP routing later)
* Added proxy information for a Mesh route, mesh gate to use and proxy seqno;
* Modified ieee80211_encap according to amendment;
* Introduced Mesh control address extension enum and removed unused struct,
also rename some structure element names.
* Modified mesh_input and added mesh_recv_* that should verify and process mesh
data frames according to 9.32 Mesh forwarding framework in amendment;
* Modified mesh_decap accordingly to changes done in mesh control AE struct;
Approved by: adrian
* Introduced ieee80211_mesh_rt_update that updates a route with the
maximum(lifetime left, new lifetime);
* Modified ieee80211_mesh_route struct by adding a lock that will be used
by both ieee80211_mesh_rt_update and precursor code (added in future commit);
* Modified in ieee80211_hwmp.c HWMP code to use new ieee80211_mesh_rt_update;
* Modified mesh_rt_flush_invalid to use new ieee80211_mesh_rt_update;
* mesh_rt_flush also checks that lifetime == 0, this gives route discovery
a change to complete;
* Modified mesh_recv_mgmt case IEEE80211_FC0_SUBTYPE_BEACON:
when ever we received a beacon from a neighbor we update route lifetime;
Approved by: adrian
* Added IEEE80211_MESH_MAX_NEIGHBORS and it is set to 15, same as before;
* Modified mesh_parse_meshpeering_action to verify MPM frame and send
correct reason code for when a frame is rejected according to standard spec;
* Modified mesh_recv_action_meshpeering_* according to the standard spec;
* Modified mesh_peer_timeout_cb to always send CLOSE frame when in CONFIRMRCV
state according to the standard spec;
Approved by: adrian
* Old struct ieee80211_meshpeer_ie had wrong peer_proto field size;
* Added IEEE80211_MPM_* size macros;
* Created an enum for the Mesh Peering Protocol Identifier field according
to the standard spec and removed old defines;
* Abbreviated Handshake Protocol is not used by the standard anymore;
* Modified mesh_verify_meshpeer to use IEEE80211_MPM_* macros for verification;
* Modified mesh_parse_meshpeering_action to parse complete frame, also to parse
it according to the standard spec;
* Modified ieee80211_add_meshpeer to construct correct MPM frames according to
the standard spec;
Approved by: adrian
* Added new action category IEEE80211_ACTION_CAT_SELF_PROT which is used by 11s
for Mesh Peering Management;
* Updated Self protected enum Action codes to start from 1 instead of 0
according to the standard spec;
* Removed old and wrong action categories IEEE80211_ACTION_CAT_MESHPEERING;
* Modified ieee80211_mesh.c and ieee80211_action.c to use the new action
category code;
* Added earlier verification code in ieee80211_input;
Approved by: adrian
Because the code lacks all the GNU extensions to printf() format stuff,
the compiler doesn't helpfully tell us that I messed up in a previous
commit.
Pointy hat to: adrian, who likely only cares about this because he's the
only one who bothers flipping on net80211 debugging.
Currently, a channel width change updates the 802.11n HT info data in
net80211 but it doesn't trigger any device changes. So the device
driver may decide that HT40 frames can be transmitted but the last
device channel set only had HT20 set.
Now, a task is scheduled so a hardware reset or change isn't done
during any active ongoing RX. It also means that it's serialised
with the other task operations (eg channel change.)
This isn't the final incantation of this work, see below.
For now, any unmodified drivers will simply receive a channel
change log entry. A subsequent patch to ath(4) will introduce
some basic channel change handling (by resetting the NIC.)
Other NICs may need to update their rate control information.
TODO:
* There's still a small window at the present moment where the
channel width has been updated but the task hasn't been fired.
The final version of this should likely pass in a channel width
field to the driver and let the driver atomically do whatever
it needs to before changing the channel.
PR: kern/166286
* Added verify_mesh_*_len functions that verify the length
according to the amendment spec and return number of destination addresses
for allocation of appropriate struct size in memory;
* Modified hwmp_recv_action_meshpath to allocate HWMP ie instead of
storing them on the stack and store all available field according the flags;
* Modify hwmp_add_mesh* to work with all cases of HWMP according to amendment.
* Modify hwmp_send_* to calculate correct len of bytes for the HWMP ie.
* Added new M_80211_MESH_* malloc defines.
* Added macros with magic numbers for HWMP ie sizes according to amendment.
* Added the external address to all HWMP ie structs.
Submitted by: monthadar@gmail.com
* Change in mesh_input to validate that QoS is set and Mesh Control field
is present, also both bytes of the QoS are read;
* Moved defragmentation in mesh_input before we try to forward packet as
inferred from amendment spec, because Mesh Control field only present in first
fragment;
* Changed in ieee80211_encap to set QoS subtype and Mesh Control field present,
only first fragment have Mesh Control field present bit equal to 1;
Submitted by: monthadar@gmail.com
* Moved old categories as specified by D4.0 to be action fields of MESH category
as specified in amendment spec;
* Modified functions to use MESH category and its action fields:
+ ieee80211_send_action_register
+ ieee80211_send_action
+ ieee80211_recv_action_register
+ieee80211_recv_action;
* Modified ieee80211_hwmp_init and hwmp_send_action so they uses correct
action fields as specified in amendment spec;
* Modified ieee80211_parse_action so that it verifies MESH frames.
* Change Mesh Link Metric to use one information element as amendment spec.
Draft 4.0 defined two different information elements for request and response.
Submitted by: monthadar@gmail.com
The scan code unlocks the comlock and calls into the driver. It then
assumes the state hasn't changed from underneath it.
Although I haven't seen this particular condition trigger, I'd like to
be informed if I or anyone else sees it.
What I'm thinking may occur:
* A cancellation comes in during the scan_end call;
* the cancel flag is set;
* but it's never checked, so scandone isn't updated;
* .. and the interface stays in the STA power save mode.
It's a subtle race, if it even exists.
PR: kern/163318
It doesn't _really_ help all that much, I'll commit something to
sys/net/if.c at some point explaining why, but the lock should be held
when checking/manipulating/branching because of said lock.
comlock, I'd like to find and analyse these cases to see if they
really are valid.
So, throw in a lock here and wait for the (hopefully!) inevitable
complaints.
* Change the mesh IE size to be IEEE80211_MESH_CONF_SZ rather than the
size of the structure;
* conf_cap is now a uint8_t rather than a uint16_t (uint16_t in D3.0,
uint8_t in the amendment spec);
* Update mesh config capability bits - earlier bits were from draft X,
current is amendment spec;
* Update the following to be an enum rather than #define and added
a VENDOR entry too from the amendment spec;
IEEE80211_MESHCONF_PATH_*
IEEE80211_MESHCONF_METRIC_*
IEEE80211_MESHCONF_CC_*
IEEE80211_MESHCONF_SYNC_*
IEEE80211_MESHCONF_AUTH_*
* Kept IEEE80211_MESHCONF_FORM_* and IEEE80211_MESHCONF_CAP_* as
defines because they are defined in a way that we need to mask in/out
information;
* In IEEE80211_MESHCONF_CAP_* IEEE80211_MESHCONF_CAP_TBTTA is removed
and 0x80 is made reserved as defined in the amendment spec.
Submitted by: monthadar@gmail.com
Reviewed by: rpaulo
compliance testing.
In order to allow for radar pattern matching to occur, the DFS CAC/NOL
handling needs to be made configurable. This commit introduces a new
sysctl, "net.wlan.dfs_debug", which controls which DFS debug mode
net80211 is in.
* 0 = default, CSA/NOL handling as per normal.
* 1 = announce a CSA, but don't add the channel to the non-occupy list
(NOL.)
* 2 = disable both CSA and NOL - only print that a radar event occured.
This code is not compiled/enabled by default as it breaks regulatory
handling. A user must enable IEEE80211_DFS_DEBUG in their kernel
configuration file for this option to become available.
Obtained from: Atheros
This makes it much easier to determine whether an event occurs in the
net80211 taskqueue (which was called "ath0 taskq") or the ath driver
taskqueue (which is also called "ath0 taskq".)
For example, this particular topology didn't work correctly from all
nodes:
[A] - [B] - [C] - [D]
Submitted by: Monthadar Al Jaberi <monthadar@gmail.com>
Reviewed by: bschmidt, adrian
This allows for multiple MAC addresses to be printed on the same
debugging line. ether_sprintf() uses a static char buffer and
thus isn't very useful here.
Submitted by: Monthadar Al Jaberi <monthadar@gmail.com>
is used.
Although the module _builds_, it fails to load because of a missing symbol from
ieee80211_tdma.c.
Specifics:
* Always build ieee80211_tdma.c in the module;
* only compile in the code if IEEE80211_SUPPORT_TDMA is defined.