mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-04 15:40:44 +00:00
net80211: deal with lost state transitions
Since5efea30f03
we can possibly lose a state transition which can cause trouble further down the road. The reproducer from643d6dce6c
can trigger these for example. Drivers for firmware based wireless cards have worked around some of this (and other) problems in the past. Add an array of tasks rather than a single one as we would simply get npending > 1 and lose order with other tasks. Try to keep state changes updated as queued in case we end up with more than one at a time. While this is not ideal either (call it a hack) it will sort the problem for now. We will queue in ieee80211_new_state_locked() and do checks there and dequeue in ieee80211_newstate_cb(). If we still overrun the (currently) 8 slots we will drop the state change rather than overwrite the last one. When dequeing we will update iv_nstate and keep it around for historic reasons for the moment. The longer term we should make the callers of ieee80211_new_state[_locked]() actually use the returned errors and act appropriately but that will touch a lot more places and drivers (possibly incl. changed behaviour for ioctls). rtwn(4) and rum(4) should probably be revisted and net80211 internals removed (for rum(4) at least the current logic still seems prone to races). PR: 271979, 271988, 275255, 263613, 274003 Sponsored by: The FreeBSD Foundation (in 2023) Reviewed by: cc Differential Revision: https://reviews.freebsd.org/D43389 (cherry picked from commit713db49d06
) Given this changes the internal structure of 'struct ieee80211vap', which gets allocated by the drivers, and we do not have enough spares, all wireless drivers need to be recompiled. Given we are forced to do the update, we leave fields in the middle of the struct and add more spares at the same time. __FreeBSD_version gets updated to 1303501 to be able to detect this change. (cherry picked from commita890a3a5dd
)
This commit is contained in:
parent
6a56d8553b
commit
a7e1fc7f62
6
UPDATING
6
UPDATING
|
@ -12,6 +12,12 @@ Items affecting the ports and packages system can be found in
|
||||||
/usr/ports/UPDATING. Please read that file before updating system packages
|
/usr/ports/UPDATING. Please read that file before updating system packages
|
||||||
and/or ports.
|
and/or ports.
|
||||||
|
|
||||||
|
20240218:
|
||||||
|
MFC of 713db49d06de changed 'struct ieee80211vap' internals in net80211.
|
||||||
|
Given we do not have enough spares and the struct is allocated by
|
||||||
|
drivers, all wireless drivers have to be recompiled.
|
||||||
|
__FreeBSD_version is updated to 1303501 to track this change.
|
||||||
|
|
||||||
20240207:
|
20240207:
|
||||||
sendmail 8.18.1 has been imported and merged. This version enforces
|
sendmail 8.18.1 has been imported and merged. This version enforces
|
||||||
stricter RFC compliance by default, especially with respect to line
|
stricter RFC compliance by default, especially with respect to line
|
||||||
|
|
|
@ -614,10 +614,12 @@ rtwn_vap_delete(struct ieee80211vap *vap)
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
struct rtwn_softc *sc = ic->ic_softc;
|
struct rtwn_softc *sc = ic->ic_softc;
|
||||||
struct rtwn_vap *uvp = RTWN_VAP(vap);
|
struct rtwn_vap *uvp = RTWN_VAP(vap);
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Put vap into INIT state + stop device if needed. */
|
/* Put vap into INIT state + stop device if needed. */
|
||||||
ieee80211_stop(vap);
|
ieee80211_stop(vap);
|
||||||
ieee80211_draintask(ic, &vap->iv_nstate_task);
|
for (i = 0; i < NET80211_IV_NSTATE_NUM; i++)
|
||||||
|
ieee80211_draintask(ic, &vap->iv_nstate_task[i]);
|
||||||
ieee80211_draintask(ic, &ic->ic_parent_task);
|
ieee80211_draintask(ic, &ic->ic_parent_task);
|
||||||
|
|
||||||
RTWN_LOCK(sc);
|
RTWN_LOCK(sc);
|
||||||
|
|
|
@ -719,10 +719,12 @@ rum_vap_delete(struct ieee80211vap *vap)
|
||||||
struct rum_vap *rvp = RUM_VAP(vap);
|
struct rum_vap *rvp = RUM_VAP(vap);
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
struct rum_softc *sc = ic->ic_softc;
|
struct rum_softc *sc = ic->ic_softc;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Put vap into INIT state. */
|
/* Put vap into INIT state. */
|
||||||
ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
|
ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
|
||||||
ieee80211_draintask(ic, &vap->iv_nstate_task);
|
for (i = 0; i < NET80211_IV_NSTATE_NUM; i++)
|
||||||
|
ieee80211_draintask(ic, &vap->iv_nstate_task[i]);
|
||||||
|
|
||||||
RUM_LOCK(sc);
|
RUM_LOCK(sc);
|
||||||
/* Cancel any unfinished Tx. */
|
/* Cancel any unfinished Tx. */
|
||||||
|
|
|
@ -729,6 +729,7 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
|
||||||
{
|
{
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
struct ifnet *ifp = vap->iv_ifp;
|
struct ifnet *ifp = vap->iv_ifp;
|
||||||
|
int i;
|
||||||
|
|
||||||
CURVNET_SET(ifp->if_vnet);
|
CURVNET_SET(ifp->if_vnet);
|
||||||
|
|
||||||
|
@ -743,7 +744,8 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
|
||||||
/*
|
/*
|
||||||
* Flush any deferred vap tasks.
|
* Flush any deferred vap tasks.
|
||||||
*/
|
*/
|
||||||
ieee80211_draintask(ic, &vap->iv_nstate_task);
|
for (i = 0; i < NET80211_IV_NSTATE_NUM; i++)
|
||||||
|
ieee80211_draintask(ic, &vap->iv_nstate_task[i]);
|
||||||
ieee80211_draintask(ic, &vap->iv_swbmiss_task);
|
ieee80211_draintask(ic, &vap->iv_swbmiss_task);
|
||||||
ieee80211_draintask(ic, &vap->iv_wme_task);
|
ieee80211_draintask(ic, &vap->iv_wme_task);
|
||||||
ieee80211_draintask(ic, &ic->ic_parent_task);
|
ieee80211_draintask(ic, &ic->ic_parent_task);
|
||||||
|
|
|
@ -470,8 +470,9 @@ _db_show_vap(const struct ieee80211vap *vap, int showmesh, int showprocs)
|
||||||
if (vap->iv_opmode == IEEE80211_M_MBSS)
|
if (vap->iv_opmode == IEEE80211_M_MBSS)
|
||||||
db_printf("(%p)", vap->iv_mesh);
|
db_printf("(%p)", vap->iv_mesh);
|
||||||
#endif
|
#endif
|
||||||
db_printf(" state %s", ieee80211_state_name[vap->iv_state]);
|
db_printf(" state %#x %s", vap->iv_state,
|
||||||
db_printf(" ifp %p(%s)", vap->iv_ifp, vap->iv_ifp->if_xname);
|
ieee80211_state_name[vap->iv_state]);
|
||||||
|
db_printf(" ifp %p(%s)", vap->iv_ifp, if_name(vap->iv_ifp));
|
||||||
db_printf("\n");
|
db_printf("\n");
|
||||||
|
|
||||||
db_printf("\tic %p", vap->iv_ic);
|
db_printf("\tic %p", vap->iv_ic);
|
||||||
|
@ -482,6 +483,16 @@ _db_show_vap(const struct ieee80211vap *vap, int showmesh, int showprocs)
|
||||||
struct sysctllog *iv_sysctl; /* dynamic sysctl context */
|
struct sysctllog *iv_sysctl; /* dynamic sysctl context */
|
||||||
#endif
|
#endif
|
||||||
db_printf("\n");
|
db_printf("\n");
|
||||||
|
|
||||||
|
db_printf("\tiv_nstate %#x %s iv_nstate_b %d iv_nstate_n %d\n",
|
||||||
|
vap->iv_nstate, ieee80211_state_name[vap->iv_nstate], /* historic */
|
||||||
|
vap->iv_nstate_b, vap->iv_nstate_n);
|
||||||
|
for (i = 0; i < NET80211_IV_NSTATE_NUM; i++) {
|
||||||
|
db_printf("\t [%d] iv_nstates %#x %s _task %p _args %d\n", i,
|
||||||
|
vap->iv_nstates[i], ieee80211_state_name[vap->iv_nstates[i]],
|
||||||
|
&vap->iv_nstate_task[i], vap->iv_nstate_args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
db_printf("\tdebug=%b\n", vap->iv_debug, IEEE80211_MSG_BITS);
|
db_printf("\tdebug=%b\n", vap->iv_debug, IEEE80211_MSG_BITS);
|
||||||
|
|
||||||
db_printf("\tflags=%b\n", vap->iv_flags, IEEE80211_F_BITS);
|
db_printf("\tflags=%b\n", vap->iv_flags, IEEE80211_F_BITS);
|
||||||
|
|
|
@ -340,7 +340,8 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
|
||||||
vap->iv_bmiss_max = IEEE80211_BMISS_MAX;
|
vap->iv_bmiss_max = IEEE80211_BMISS_MAX;
|
||||||
callout_init_mtx(&vap->iv_swbmiss, IEEE80211_LOCK_OBJ(ic), 0);
|
callout_init_mtx(&vap->iv_swbmiss, IEEE80211_LOCK_OBJ(ic), 0);
|
||||||
callout_init(&vap->iv_mgtsend, 1);
|
callout_init(&vap->iv_mgtsend, 1);
|
||||||
TASK_INIT(&vap->iv_nstate_task, 0, ieee80211_newstate_cb, vap);
|
for (i = 0; i < NET80211_IV_NSTATE_NUM; i++)
|
||||||
|
TASK_INIT(&vap->iv_nstate_task[i], 0, ieee80211_newstate_cb, vap);
|
||||||
TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss, vap);
|
TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss, vap);
|
||||||
TASK_INIT(&vap->iv_wme_task, 0, vap_update_wme, vap);
|
TASK_INIT(&vap->iv_wme_task, 0, vap_update_wme, vap);
|
||||||
TASK_INIT(&vap->iv_slot_task, 0, vap_update_slot, vap);
|
TASK_INIT(&vap->iv_slot_task, 0, vap_update_slot, vap);
|
||||||
|
@ -2497,6 +2498,51 @@ wakeupwaiting(struct ieee80211vap *vap0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_ieee80211_newstate_get_next_empty_slot(struct ieee80211vap *vap)
|
||||||
|
{
|
||||||
|
int nstate_num;
|
||||||
|
|
||||||
|
IEEE80211_LOCK_ASSERT(vap->iv_ic);
|
||||||
|
|
||||||
|
if (vap->iv_nstate_n >= NET80211_IV_NSTATE_NUM)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
nstate_num = vap->iv_nstate_b + vap->iv_nstate_n;
|
||||||
|
nstate_num %= NET80211_IV_NSTATE_NUM;
|
||||||
|
vap->iv_nstate_n++;
|
||||||
|
|
||||||
|
return (nstate_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_ieee80211_newstate_get_next_pending_slot(struct ieee80211vap *vap)
|
||||||
|
{
|
||||||
|
int nstate_num;
|
||||||
|
|
||||||
|
IEEE80211_LOCK_ASSERT(vap->iv_ic);
|
||||||
|
|
||||||
|
KASSERT(vap->iv_nstate_n > 0, ("%s: vap %p iv_nstate_n %d\n",
|
||||||
|
__func__, vap, vap->iv_nstate_n));
|
||||||
|
|
||||||
|
nstate_num = vap->iv_nstate_b;
|
||||||
|
vap->iv_nstate_b++;
|
||||||
|
if (vap->iv_nstate_b >= NET80211_IV_NSTATE_NUM)
|
||||||
|
vap->iv_nstate_b = 0;
|
||||||
|
vap->iv_nstate_n--;
|
||||||
|
|
||||||
|
return (nstate_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_ieee80211_newstate_get_npending(struct ieee80211vap *vap)
|
||||||
|
{
|
||||||
|
|
||||||
|
IEEE80211_LOCK_ASSERT(vap->iv_ic);
|
||||||
|
|
||||||
|
return (vap->iv_nstate_n);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle post state change work common to all operating modes.
|
* Handle post state change work common to all operating modes.
|
||||||
*/
|
*/
|
||||||
|
@ -2506,17 +2552,25 @@ ieee80211_newstate_cb(void *xvap, int npending)
|
||||||
struct ieee80211vap *vap = xvap;
|
struct ieee80211vap *vap = xvap;
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
enum ieee80211_state nstate, ostate;
|
enum ieee80211_state nstate, ostate;
|
||||||
int arg, rc;
|
int arg, rc, nstate_num;
|
||||||
|
|
||||||
|
KASSERT(npending == 1, ("%s: vap %p with npending %d != 1\n",
|
||||||
|
__func__, vap, npending));
|
||||||
IEEE80211_LOCK(ic);
|
IEEE80211_LOCK(ic);
|
||||||
nstate = vap->iv_nstate;
|
nstate_num = _ieee80211_newstate_get_next_pending_slot(vap);
|
||||||
arg = vap->iv_nstate_arg;
|
|
||||||
|
/*
|
||||||
|
* Update the historic fields for now as they are used in some
|
||||||
|
* drivers and reduce code changes for now.
|
||||||
|
*/
|
||||||
|
vap->iv_nstate = nstate = vap->iv_nstates[nstate_num];
|
||||||
|
arg = vap->iv_nstate_args[nstate_num];
|
||||||
|
|
||||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
||||||
"%s:%d: running state update %s -> %s (%d)\n",
|
"%s:%d: running state update %s -> %s (%d)\n",
|
||||||
__func__, __LINE__,
|
__func__, __LINE__,
|
||||||
ieee80211_state_name[vap->iv_state],
|
ieee80211_state_name[vap->iv_state],
|
||||||
ieee80211_state_name[vap->iv_nstate],
|
ieee80211_state_name[nstate],
|
||||||
npending);
|
npending);
|
||||||
|
|
||||||
if (vap->iv_flags_ext & IEEE80211_FEXT_REINIT) {
|
if (vap->iv_flags_ext & IEEE80211_FEXT_REINIT) {
|
||||||
|
@ -2527,9 +2581,10 @@ ieee80211_newstate_cb(void *xvap, int npending)
|
||||||
/* Deny any state changes while we are here. */
|
/* Deny any state changes while we are here. */
|
||||||
vap->iv_nstate = IEEE80211_S_INIT;
|
vap->iv_nstate = IEEE80211_S_INIT;
|
||||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
||||||
"%s: %s -> %s arg %d\n", __func__,
|
"%s: %s -> %s arg %d -> %s arg %d\n", __func__,
|
||||||
ieee80211_state_name[vap->iv_state],
|
ieee80211_state_name[vap->iv_state],
|
||||||
ieee80211_state_name[vap->iv_nstate], arg);
|
ieee80211_state_name[vap->iv_nstate], 0,
|
||||||
|
ieee80211_state_name[nstate], arg);
|
||||||
vap->iv_newstate(vap, vap->iv_nstate, 0);
|
vap->iv_newstate(vap, vap->iv_nstate, 0);
|
||||||
IEEE80211_LOCK_ASSERT(ic);
|
IEEE80211_LOCK_ASSERT(ic);
|
||||||
vap->iv_flags_ext &= ~(IEEE80211_FEXT_REINIT |
|
vap->iv_flags_ext &= ~(IEEE80211_FEXT_REINIT |
|
||||||
|
@ -2670,7 +2725,7 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
struct ieee80211vap *vp;
|
struct ieee80211vap *vp;
|
||||||
enum ieee80211_state ostate;
|
enum ieee80211_state ostate;
|
||||||
int nrunning, nscanning;
|
int nrunning, nscanning, nstate_num;
|
||||||
|
|
||||||
IEEE80211_LOCK_ASSERT(ic);
|
IEEE80211_LOCK_ASSERT(ic);
|
||||||
|
|
||||||
|
@ -2692,14 +2747,6 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
|
||||||
ieee80211_state_name[nstate],
|
ieee80211_state_name[nstate],
|
||||||
ieee80211_state_name[vap->iv_nstate]);
|
ieee80211_state_name[vap->iv_nstate]);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (vap->iv_state != vap->iv_nstate) {
|
|
||||||
/* Warn if the previous state hasn't completed. */
|
|
||||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
|
||||||
"%s:%d: pending %s -> %s (now to %s) transition lost\n",
|
|
||||||
__func__, __LINE__,
|
|
||||||
ieee80211_state_name[vap->iv_state],
|
|
||||||
ieee80211_state_name[vap->iv_nstate],
|
|
||||||
ieee80211_state_name[nstate]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2722,7 +2769,16 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
|
||||||
nscanning++;
|
nscanning++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ostate = vap->iv_state;
|
/*
|
||||||
|
* Look ahead for the "old state" at that point when the last queued
|
||||||
|
* state transition is run.
|
||||||
|
*/
|
||||||
|
if (vap->iv_nstate_n == 0) {
|
||||||
|
ostate = vap->iv_state;
|
||||||
|
} else {
|
||||||
|
nstate_num = (vap->iv_nstate_b + vap->iv_nstate_n - 1) % NET80211_IV_NSTATE_NUM;
|
||||||
|
ostate = vap->iv_nstates[nstate_num];
|
||||||
|
}
|
||||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
|
||||||
"%s: %s -> %s (arg %d) (nrunning %d nscanning %d)\n", __func__,
|
"%s: %s -> %s (arg %d) (nrunning %d nscanning %d)\n", __func__,
|
||||||
ieee80211_state_name[ostate], ieee80211_state_name[nstate], arg,
|
ieee80211_state_name[ostate], ieee80211_state_name[nstate], arg,
|
||||||
|
@ -2816,11 +2872,37 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* defer the state change to a thread */
|
/*
|
||||||
vap->iv_nstate = nstate;
|
* Defer the state change to a thread.
|
||||||
vap->iv_nstate_arg = arg;
|
* We support up-to NET80211_IV_NSTATE_NUM pending state changes
|
||||||
|
* using a separate task for each. Otherwise, if we enqueue
|
||||||
|
* more than one state change they will be folded together,
|
||||||
|
* npedning will be > 1 and we may run then out of sequence with
|
||||||
|
* other events.
|
||||||
|
* This is kind-of a hack after 10 years but we know how to provoke
|
||||||
|
* these cases now (and seen them in the wild).
|
||||||
|
*/
|
||||||
|
nstate_num = _ieee80211_newstate_get_next_empty_slot(vap);
|
||||||
|
if (nstate_num == -1) {
|
||||||
|
/*
|
||||||
|
* This is really bad and we should just go kaboom.
|
||||||
|
* Instead drop it. No one checks the return code anyway.
|
||||||
|
*/
|
||||||
|
ic_printf(ic, "%s:%d: pending %s -> %s (now to %s) "
|
||||||
|
"transition lost. %d/%d pending state changes:\n",
|
||||||
|
__func__, __LINE__,
|
||||||
|
ieee80211_state_name[vap->iv_state],
|
||||||
|
ieee80211_state_name[vap->iv_nstate],
|
||||||
|
ieee80211_state_name[nstate],
|
||||||
|
_ieee80211_newstate_get_npending(vap),
|
||||||
|
NET80211_IV_NSTATE_NUM);
|
||||||
|
|
||||||
|
return (EAGAIN);
|
||||||
|
}
|
||||||
|
vap->iv_nstates[nstate_num] = nstate;
|
||||||
|
vap->iv_nstate_args[nstate_num] = arg;
|
||||||
vap->iv_flags_ext |= IEEE80211_FEXT_STATEWAIT;
|
vap->iv_flags_ext |= IEEE80211_FEXT_STATEWAIT;
|
||||||
ieee80211_runtask(ic, &vap->iv_nstate_task);
|
ieee80211_runtask(ic, &vap->iv_nstate_task[nstate_num]);
|
||||||
return EINPROGRESS;
|
return EINPROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,9 +410,16 @@ struct ieee80211vap {
|
||||||
uint32_t iv_com_state; /* com usage / detached flag */
|
uint32_t iv_com_state; /* com usage / detached flag */
|
||||||
enum ieee80211_opmode iv_opmode; /* operation mode */
|
enum ieee80211_opmode iv_opmode; /* operation mode */
|
||||||
enum ieee80211_state iv_state; /* state machine state */
|
enum ieee80211_state iv_state; /* state machine state */
|
||||||
enum ieee80211_state iv_nstate; /* pending state */
|
|
||||||
int iv_nstate_arg; /* pending state arg */
|
/* Deferred state processing. */
|
||||||
struct task iv_nstate_task; /* deferred state processing */
|
enum ieee80211_state iv_nstate; /* next pending state (historic) */
|
||||||
|
#define NET80211_IV_NSTATE_NUM 8
|
||||||
|
int iv_nstate_b; /* First filled slot. */
|
||||||
|
int iv_nstate_n; /* # of filled slots. */
|
||||||
|
enum ieee80211_state iv_nstates[NET80211_IV_NSTATE_NUM]; /* queued pending state(s) */
|
||||||
|
int iv_nstate_args[NET80211_IV_NSTATE_NUM]; /* queued pending state(s) arg */
|
||||||
|
struct task iv_nstate_task[NET80211_IV_NSTATE_NUM];
|
||||||
|
|
||||||
struct task iv_swbmiss_task;/* deferred iv_bmiss call */
|
struct task iv_swbmiss_task;/* deferred iv_bmiss call */
|
||||||
struct callout iv_mgtsend; /* mgmt frame response timer */
|
struct callout iv_mgtsend; /* mgmt frame response timer */
|
||||||
/* inactivity timer settings */
|
/* inactivity timer settings */
|
||||||
|
@ -604,10 +611,7 @@ struct ieee80211vap {
|
||||||
struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
|
struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
|
||||||
struct ieee80211_node *);
|
struct ieee80211_node *);
|
||||||
|
|
||||||
#ifdef __ILP32__
|
uint64_t iv_spare[36];
|
||||||
uint32_t iv_spare0;
|
|
||||||
#endif
|
|
||||||
uint64_t iv_spare[5];
|
|
||||||
};
|
};
|
||||||
MALLOC_DECLARE(M_80211_VAP);
|
MALLOC_DECLARE(M_80211_VAP);
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
* in the range 5 to 9.
|
* in the range 5 to 9.
|
||||||
*/
|
*/
|
||||||
#undef __FreeBSD_version
|
#undef __FreeBSD_version
|
||||||
#define __FreeBSD_version 1303500 /* Master, propagated to newvers */
|
#define __FreeBSD_version 1303501 /* Master, propagated to newvers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||||
|
|
Loading…
Reference in a new issue