Update 802.11s mesh support to draft 3.03. This includes a revised frame

format for peering and changes to the PERR frames.
Note that this is incompatible with the previous code.

Reviewed by:	sam
MFC after:	1 week
This commit is contained in:
Rui Paulo 2009-09-22 18:18:14 +00:00
parent f0fda3a508
commit c77735e28f
4 changed files with 125 additions and 199 deletions

View File

@ -708,7 +708,7 @@ enum {
IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
/*
* 802.11s IEs based on D3.0 spec and were not assigned by
* 802.11s IEs based on D3.03 spec and were not assigned by
* ANA. Beware changing them because some of them are being
* kept compatible with Linux.
*/
@ -726,10 +726,9 @@ enum {
IEEE80211_ELEMID_MESHPREQ = 68,
IEEE80211_ELEMID_MESHPREP = 69,
IEEE80211_ELEMID_MESHPERR = 70,
IEEE80211_ELEMID_MESHPU = 53,
IEEE80211_ELEMID_MESHPUC = 54,
IEEE80211_ELEMID_MESHPXU = 53,
IEEE80211_ELEMID_MESHPXUC = 54,
IEEE80211_ELEMID_MESHAH = 60, /* Abbreviated Handshake */
IEEE80211_ELEMID_MESHPEERVER = 80, /* Peering Protocol Version */
};
struct ieee80211_tim_ie {
@ -925,6 +924,9 @@ enum {
IEEE80211_REASON_MESH_INVALID_GTK = 8, /* 11s */
IEEE80211_REASON_MESH_INCONS_PARAMS = 9, /* 11s */
IEEE80211_REASON_MESH_INVALID_SECURITY = 10, /* 11s */
IEEE80211_REASON_MESH_PERR_UNSPEC = 11, /* 11s */
IEEE80211_REASON_MESH_PERR_NO_FI = 12, /* 11s */
IEEE80211_REASON_MESH_PERR_DEST_UNREACH = 13, /* 11s */
IEEE80211_STATUS_SUCCESS = 0,
IEEE80211_STATUS_UNSPECIFIED = 1,

View File

@ -188,10 +188,7 @@ SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rannint, CTLTYPE_INT | CTLFLAG_RW,
#define IEEE80211_HWMP_DEFAULT_MAXHOPS 31
static ieee80211_recv_action_func hwmp_recv_action_meshpath_preq;
static ieee80211_recv_action_func hwmp_recv_action_meshpath_prep;
static ieee80211_recv_action_func hwmp_recv_action_meshpath_perr;
static ieee80211_recv_action_func hwmp_recv_action_meshpath_rann;
static ieee80211_recv_action_func hwmp_recv_action_meshpath;
static struct ieee80211_mesh_proto_path mesh_proto_hwmp = {
.mpp_descr = "HWMP",
@ -217,16 +214,10 @@ ieee80211_hwmp_init(void)
ieee80211_hwmp_rannint = msecs_to_ticks(1*1000);
/*
* Register action frame handlers.
* Register action frame handler.
*/
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
IEEE80211_ACTION_MESHPATH_REQ, hwmp_recv_action_meshpath_preq);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
IEEE80211_ACTION_MESHPATH_REP, hwmp_recv_action_meshpath_prep);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
IEEE80211_ACTION_MESHPATH_ERR, hwmp_recv_action_meshpath_perr);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
IEEE80211_ACTION_MESHPATH_RANN, hwmp_recv_action_meshpath_rann);
IEEE80211_ACTION_MESHPATH_SEL, hwmp_recv_action_meshpath);
/* NB: default is 5 secs per spec */
mesh_proto_hwmp.mpp_inact = msecs_to_ticks(5*1000);
@ -285,17 +276,23 @@ hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
}
static int
hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni,
hwmp_recv_action_meshpath(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_meshpreq_ie preq;
struct ieee80211_meshprep_ie prep;
struct ieee80211_meshperr_ie perr;
struct ieee80211_meshrann_ie rann;
const uint8_t *iefrm = frm + 2; /* action + code */
int found = 0;
while (efrm - iefrm > 1) {
IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
if (*iefrm == IEEE80211_ELEMID_MESHPREQ) {
switch (*iefrm) {
case IEEE80211_ELEMID_MESHPREQ:
{
const struct ieee80211_meshpreq_ie *mpreq =
(const struct ieee80211_meshpreq_ie *) iefrm;
/* XXX > 1 target */
@ -305,7 +302,7 @@ hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni,
IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PREQ with wrong len");
vap->iv_stats.is_rx_mgtdiscard++;
return 1;
break;
}
memcpy(&preq, mpreq, sizeof(preq));
preq.preq_id = LE_READ_4(&mpreq->preq_id);
@ -315,28 +312,11 @@ hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni,
preq.preq_targets[0].target_seq =
LE_READ_4(&mpreq->preq_targets[0].target_seq);
hwmp_recv_preq(vap, ni, wh, &preq);
return 0;
found++;
break;
}
iefrm += iefrm[1] + 2;
}
IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PREQ without IE");
vap->iv_stats.is_rx_mgtdiscard++;
return 0;
}
static int
hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_meshprep_ie prep;
const uint8_t *iefrm = frm + 2; /* action + code */
while (efrm - iefrm > 1) {
IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
if (*iefrm == IEEE80211_ELEMID_MESHPREP) {
case IEEE80211_ELEMID_MESHPREP:
{
const struct ieee80211_meshprep_ie *mprep =
(const struct ieee80211_meshprep_ie *) iefrm;
if (mprep->prep_len !=
@ -345,7 +325,7 @@ hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni,
IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PREP with wrong len");
vap->iv_stats.is_rx_mgtdiscard++;
return 1;
break;
}
memcpy(&prep, mprep, sizeof(prep));
prep.prep_targetseq = LE_READ_4(&mprep->prep_targetseq);
@ -353,28 +333,11 @@ hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni,
prep.prep_metric = LE_READ_4(&mprep->prep_metric);
prep.prep_origseq = LE_READ_4(&mprep->prep_origseq);
hwmp_recv_prep(vap, ni, wh, &prep);
return 0;
found++;
break;
}
iefrm += iefrm[1] + 2;
}
IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PREP without IE");
vap->iv_stats.is_rx_mgtdiscard++;
return 0;
}
static int
hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
struct ieee80211_meshperr_ie perr;
struct ieee80211vap *vap = ni->ni_vap;
const uint8_t *iefrm = frm + 2; /* action + code */
while (efrm - iefrm > 1) {
IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
if (*iefrm == IEEE80211_ELEMID_MESHPERR) {
case IEEE80211_ELEMID_MESHPERR:
{
const struct ieee80211_meshperr_ie *mperr =
(const struct ieee80211_meshperr_ie *) iefrm;
/* XXX > 1 target */
@ -384,34 +347,17 @@ hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni,
IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PERR with wrong len");
vap->iv_stats.is_rx_mgtdiscard++;
return 1;
break;
}
memcpy(&perr, mperr, sizeof(perr));
perr.perr_dests[0].dest_seq =
LE_READ_4(&mperr->perr_dests[0].dest_seq);
hwmp_recv_perr(vap, ni, wh, &perr);
return 0;
found++;
break;
}
iefrm += iefrm[1] + 2;
}
IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PERR without IE");
vap->iv_stats.is_rx_mgtdiscard++;
return 0;
}
static int
hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_meshrann_ie rann;
const uint8_t *iefrm = frm + 2; /* action + code */
while (efrm - iefrm > 1) {
IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
if (*iefrm == IEEE80211_ELEMID_MESHRANN) {
case IEEE80211_ELEMID_MESHRANN:
{
const struct ieee80211_meshrann_ie *mrann =
(const struct ieee80211_meshrann_ie *) iefrm;
if (mrann->rann_len !=
@ -426,13 +372,18 @@ hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni,
rann.rann_seq = LE_READ_4(&mrann->rann_seq);
rann.rann_metric = LE_READ_4(&mrann->rann_metric);
hwmp_recv_rann(vap, ni, wh, &rann);
return 0;
found++;
break;
}
}
iefrm += iefrm[1] + 2;
}
IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "RANN without IE");
vap->iv_stats.is_rx_mgtdiscard++;
if (!found) {
IEEE80211_DISCARD(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "PATH SEL action without IE");
vap->iv_stats.is_rx_mgtdiscard++;
}
return 0;
}
@ -480,24 +431,21 @@ hwmp_send_action(struct ieee80211_node *ni,
return ENOMEM;
}
*frm++ = IEEE80211_ACTION_CAT_MESHPATH;
*frm++ = IEEE80211_ACTION_MESHPATH_SEL;
switch (*ie) {
case IEEE80211_ELEMID_MESHPREQ:
*frm++ = IEEE80211_ACTION_MESHPATH_REQ;
frm = hwmp_add_meshpreq(frm,
(struct ieee80211_meshpreq_ie *)ie);
break;
case IEEE80211_ELEMID_MESHPREP:
*frm++ = IEEE80211_ACTION_MESHPATH_REP;
frm = hwmp_add_meshprep(frm,
(struct ieee80211_meshprep_ie *)ie);
break;
case IEEE80211_ELEMID_MESHPERR:
*frm++ = IEEE80211_ACTION_MESHPATH_ERR;
frm = hwmp_add_meshperr(frm,
(struct ieee80211_meshperr_ie *)ie);
break;
case IEEE80211_ELEMID_MESHRANN:
*frm++ = IEEE80211_ACTION_MESHPATH_RANN;
frm = hwmp_add_meshrann(frm,
(struct ieee80211_meshrann_ie *)ie);
break;
@ -528,6 +476,11 @@ hwmp_send_action(struct ieee80211_node *ni,
return ic->ic_raw_xmit(ni, m, &params);
}
#define ADDSHORT(frm, v) do { \
frm[0] = (v) & 0xff; \
frm[1] = (v) >> 8; \
frm += 2; \
} while (0)
#define ADDWORD(frm, v) do { \
LE_WRITE_4(frm, v); \
frm += 4; \
@ -592,12 +545,14 @@ hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr)
*frm++ = IEEE80211_ELEMID_MESHPERR;
*frm++ = sizeof(struct ieee80211_meshperr_ie) - 2 +
(perr->perr_ndests - 1) * sizeof(*perr->perr_dests);
*frm++ = perr->perr_mode;
*frm++ = perr->perr_ttl;
*frm++ = perr->perr_ndests;
for (i = 0; i < perr->perr_ndests; i++) {
*frm += perr->perr_dests[i].dest_flags;
IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr);
frm += 6;
ADDWORD(frm, perr->perr_dests[i].dest_seq);
ADDSHORT(frm, perr->perr_dests[i].dest_rcode);
}
return frm;
}
@ -1138,12 +1093,15 @@ hwmp_send_prep(struct ieee80211_node *ni,
sizeof(struct ieee80211_meshprep_ie));
}
#define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags
#define PERR_DADDR(n) perr.perr_dests[n].dest_addr
#define PERR_DSEQ(n) perr.perr_dests[n].dest_seq
#define PERR_DRCODE(n) perr.perr_dests[n].dest_rcode
static void
hwmp_peerdown(struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_meshperr_ie perr;
struct ieee80211_mesh_route *rt;
struct ieee80211_hwmp_route *hr;
@ -1154,19 +1112,27 @@ hwmp_peerdown(struct ieee80211_node *ni)
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"%s", "delete route entry");
perr.perr_mode = 0;
perr.perr_ttl = ms->ms_ttl;
perr.perr_ndests = 1;
if (hr->hr_seq == 0)
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN;
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC;
IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest);
PERR_DSEQ(0) = hr->hr_seq;
PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH;
/* NB: flush everything passing through peer */
ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr);
hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr);
}
#undef PERR_DFLAGS
#undef PERR_DADDR
#undef PERR_DSEQ
#undef PERR_DRCODE
#define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags
#define PERR_DADDR(n) perr->perr_dests[n].dest_addr
#define PERR_DSEQ(n) perr->perr_dests[n].dest_seq
#define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode
static void
hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
const struct ieee80211_frame *wh, const struct ieee80211_meshperr_ie *perr)
@ -1192,9 +1158,9 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i));
if (rt == NULL)
continue;
hr = IEEE80211_MESH_ROUTE_PRIV(rt,
struct ieee80211_hwmp_route);
if (HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) {
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) &&
HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) {
ieee80211_mesh_rt_del(vap, rt->rt_dest);
ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest);
rt = NULL;
@ -1205,10 +1171,11 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
* Propagate the PERR if we previously found it on our routing table.
* XXX handle ndest > 1
*/
if (forward) {
if (forward && perr->perr_ttl > 1) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"propagate PERR from %s", ether_sprintf(wh->i_addr2));
memcpy(&pperr, perr, sizeof(*perr));
pperr.perr_ttl--;
hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr,
&pperr);
}

View File

@ -87,10 +87,10 @@ static void mesh_peer_timeout_backoff(struct ieee80211_node *);
static void mesh_peer_timeout_cb(void *);
static __inline void
mesh_peer_timeout_stop(struct ieee80211_node *);
static int mesh_verify_meshpeerver(struct ieee80211vap *, const uint8_t *);
static int mesh_verify_meshid(struct ieee80211vap *, const uint8_t *);
static int mesh_verify_meshconf(struct ieee80211vap *, const uint8_t *);
static int mesh_verify_meshpeer(struct ieee80211vap *, const uint8_t *);
static int mesh_verify_meshpeer(struct ieee80211vap *, uint8_t,
const uint8_t *);
uint32_t mesh_airtime_calc(struct ieee80211_node *);
/*
@ -1544,19 +1544,16 @@ static const struct ieee80211_meshpeer_ie *
mesh_parse_meshpeering_action(struct ieee80211_node *ni,
const struct ieee80211_frame *wh, /* XXX for VERIFY_LENGTH */
const uint8_t *frm, const uint8_t *efrm,
struct ieee80211_meshpeer_ie *mp)
struct ieee80211_meshpeer_ie *mp, uint8_t subtype)
{
struct ieee80211vap *vap = ni->ni_vap;
const struct ieee80211_meshpeer_ie *mpie;
const uint8_t *meshid, *meshconf, *meshpeerver, *meshpeer;
const uint8_t *meshid, *meshconf, *meshpeer;
meshid = meshconf = meshpeerver = meshpeer = NULL;
meshid = meshconf = meshpeer = NULL;
while (efrm - frm > 1) {
IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL);
switch (*frm) {
case IEEE80211_ELEMID_MESHPEERVER:
meshpeerver = frm;
break;
case IEEE80211_ELEMID_MESHID:
meshid = frm;
break;
@ -1567,12 +1564,10 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni,
meshpeer = frm;
mpie = (const struct ieee80211_meshpeer_ie *) frm;
memset(mp, 0, sizeof(*mp));
mp->peer_subtype = mpie->peer_subtype;
mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
/* NB: peer link ID is optional on these frames */
if (mpie->peer_subtype ==
IEEE80211_MESH_PEER_LINK_CLOSE &&
mpie->peer_len == 5) {
if (subtype == IEEE80211_MESH_PEER_LINK_CLOSE &&
mpie->peer_len == 8) {
mp->peer_linkid = 0;
mp->peer_rcode = LE_READ_2(&mpie->peer_linkid);
} else {
@ -1589,12 +1584,12 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni,
* close subtype don't have a Mesh Configuration IE.
* If if fails validation, close the peer link.
*/
KASSERT(meshpeer != NULL && mp->peer_subtype !=
IEEE80211_ACTION_MESHPEERING_CLOSE, ("parsing close action"));
KASSERT(meshpeer != NULL &&
subtype != IEEE80211_ACTION_MESHPEERING_CLOSE,
("parsing close action"));
if (mesh_verify_meshpeerver(vap, meshpeerver) ||
mesh_verify_meshid(vap, meshid) ||
mesh_verify_meshpeer(vap, meshpeer) ||
if (mesh_verify_meshid(vap, meshid) ||
mesh_verify_meshpeer(vap, subtype, meshpeer) ||
mesh_verify_meshconf(vap, meshconf)) {
uint16_t args[3];
@ -1638,7 +1633,8 @@ mesh_recv_action_meshpeering_open(struct ieee80211_node *ni,
uint16_t args[3];
/* +2+2 for action + code + capabilites */
meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie);
meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie,
IEEE80211_ACTION_MESHPEERING_OPEN);
if (meshpeer == NULL) {
return 0;
}
@ -1770,7 +1766,8 @@ mesh_recv_action_meshpeering_confirm(struct ieee80211_node *ni,
uint16_t args[3];
/* +2+2+2+2 for action + code + capabilites + status code + AID */
meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie);
meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie,
IEEE80211_ACTION_MESHPEERING_CONFIRM);
if (meshpeer == NULL) {
return 0;
}
@ -1933,7 +1930,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni,
ic->ic_headroom + sizeof(struct ieee80211_frame),
sizeof(uint16_t) /* action+category */
+ sizeof(uint16_t) /* capabilites */
+ sizeof(struct ieee80211_meshpeerver_ie)
+ 2 + IEEE80211_RATE_SIZE
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
+ 2 + IEEE80211_MESHID_LEN
@ -1946,7 +1942,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni,
* [1] category
* [1] action
* [2] capabilities
* [tlv] mesh peer protocol version
* [tlv] rates
* [tlv] xrates
* [tlv] mesh id
@ -1956,7 +1951,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni,
*frm++ = category;
*frm++ = action;
ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
frm = ieee80211_add_meshpeerver(frm, vap);
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
frm = ieee80211_add_rates(frm, rs);
frm = ieee80211_add_xrates(frm, rs);
@ -1999,7 +1993,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni,
+ sizeof(uint16_t) /* capabilites */
+ sizeof(uint16_t) /* status code */
+ sizeof(uint16_t) /* AID */
+ sizeof(struct ieee80211_meshpeerver_ie)
+ 2 + IEEE80211_RATE_SIZE
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
+ 2 + IEEE80211_MESHID_LEN
@ -2014,7 +2007,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni,
* [2] capabilities
* [2] status code
* [2] association id (peer ID)
* [tlv] mesh peer protocol version
* [tlv] rates
* [tlv] xrates
* [tlv] mesh id
@ -2026,7 +2018,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni,
ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
ADDSHORT(frm, 0); /* status code */
ADDSHORT(frm, args[1]); /* AID */
frm = ieee80211_add_meshpeerver(frm, vap);
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
frm = ieee80211_add_rates(frm, rs);
frm = ieee80211_add_xrates(frm, rs);
@ -2067,7 +2058,6 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
ic->ic_headroom + sizeof(struct ieee80211_frame),
sizeof(uint16_t) /* action+category */
+ sizeof(uint16_t) /* reason code */
+ sizeof(struct ieee80211_meshpeerver_ie)
+ 2 + IEEE80211_MESHID_LEN
+ sizeof(struct ieee80211_meshpeer_ie)
);
@ -2077,14 +2067,12 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
* [1] category
* [1] action
* [2] reason code
* [tlv] mesh peer protocol version
* [tlv] mesh id
* [tlv] mesh peer link mgmt
*/
*frm++ = category;
*frm++ = action;
ADDSHORT(frm, args[2]); /* reason code */
frm = ieee80211_add_meshpeerver(frm, vap);
frm = ieee80211_add_meshid(frm, vap);
frm = ieee80211_add_meshpeer(frm,
IEEE80211_MESH_PEER_LINK_CLOSE,
@ -2278,19 +2266,6 @@ mesh_peer_timeout_cb(void *arg)
}
}
static int
mesh_verify_meshpeerver(struct ieee80211vap *vap, const uint8_t *ie)
{
static const uint8_t peer[4] = IEEE80211_MESHPEERVER_PEER;
const struct ieee80211_meshpeerver_ie *meshpeerver =
(const struct ieee80211_meshpeerver_ie *) ie;
if (meshpeerver->peerver_len !=
sizeof(struct ieee80211_meshpeerver_ie) - 2)
return 1;
return memcmp(meshpeerver->peerver_proto, peer, 4);
}
static int
mesh_verify_meshid(struct ieee80211vap *vap, const uint8_t *ie)
{
@ -2364,26 +2339,28 @@ mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie)
}
static int
mesh_verify_meshpeer(struct ieee80211vap *vap, const uint8_t *ie)
mesh_verify_meshpeer(struct ieee80211vap *vap, uint8_t subtype,
const uint8_t *ie)
{
const struct ieee80211_meshpeer_ie *meshpeer =
(const struct ieee80211_meshpeer_ie *) ie;
if (meshpeer == NULL)
if (meshpeer == NULL || meshpeer->peer_len < 6 ||
meshpeer->peer_len > 10)
return 1;
switch (meshpeer->peer_subtype) {
switch (subtype) {
case IEEE80211_MESH_PEER_LINK_OPEN:
if (meshpeer->peer_len != 3)
if (meshpeer->peer_len != 6)
return 1;
break;
case IEEE80211_MESH_PEER_LINK_CONFIRM:
if (meshpeer->peer_len != 5)
if (meshpeer->peer_len != 8)
return 1;
break;
case IEEE80211_MESH_PEER_LINK_CLOSE:
if (meshpeer->peer_len < 5)
if (meshpeer->peer_len < 8)
return 1;
if (meshpeer->peer_len == 5 && meshpeer->peer_linkid != 0)
if (meshpeer->peer_len == 8 && meshpeer->peer_linkid != 0)
return 1;
if (meshpeer->peer_rcode == 0)
return 1;
@ -2448,25 +2425,6 @@ ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap)
return frm;
}
/*
* Add a Mesh Peer Protocol IE to a frame.
* XXX: needs to grow support for Abbreviated Handshake
*/
uint8_t *
ieee80211_add_meshpeerver(uint8_t *frm, struct ieee80211vap *vap)
{
static struct ieee80211_meshpeerver_ie ie = {
.peerver_ie = IEEE80211_ELEMID_MESHPEERVER,
.peerver_len = 4,
.peerver_proto = IEEE80211_MESHPEERVER_PEER,
};
KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
memcpy(frm, &ie, sizeof(ie));
return frm + sizeof(ie);
}
/*
* Add a Mesh Peer Management IE to a frame.
*/
@ -2474,28 +2432,34 @@ uint8_t *
ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid,
uint16_t peerid, uint16_t reason)
{
/* XXX change for AH */
static const uint8_t meshpeerproto[4] = IEEE80211_MESH_PEER_PROTO;
KASSERT(localid != 0, ("localid == 0"));
*frm++ = IEEE80211_ELEMID_MESHPEER;
switch (subtype) {
case IEEE80211_MESH_PEER_LINK_OPEN:
*frm++ = 3; /* length */
*frm++ = subtype;
*frm++ = 6; /* length */
memcpy(frm, meshpeerproto, 4);
frm += 4;
ADDSHORT(frm, localid); /* local ID */
break;
case IEEE80211_MESH_PEER_LINK_CONFIRM:
KASSERT(peerid != 0, ("sending peer confirm without peer id"));
*frm++ = 5; /* length */
*frm++ = subtype;
*frm++ = 8; /* length */
memcpy(frm, meshpeerproto, 4);
frm += 4;
ADDSHORT(frm, localid); /* local ID */
ADDSHORT(frm, peerid); /* peer ID */
break;
case IEEE80211_MESH_PEER_LINK_CLOSE:
if (peerid)
*frm++ = 7; /* length */
*frm++ = 10; /* length */
else
*frm++ = 5; /* length */
*frm++ = subtype;
*frm++ = 8; /* length */
memcpy(frm, meshpeerproto, 4);
frm += 4;
ADDSHORT(frm, localid); /* local ID */
if (peerid)
ADDSHORT(frm, peerid); /* peer ID */

View File

@ -34,7 +34,7 @@
#define IEEE80211_MESH_DEFAULT_TTL 31
/*
* NB: all structures are__packed so sizeof works on arm, et. al.
* NB: all structures are __packed so sizeof works on arm, et. al.
*/
/*
* 802.11s Information Elements.
@ -116,28 +116,11 @@ struct ieee80211_meshcngst_ie {
AC_BE, AC_VI, AC_VO */
} __packed;
/* Peer Version */
struct ieee80211_meshpeerver_ie {
uint8_t peerver_ie; /* IEEE80211_ELEMID_MESHPEERVER */
uint8_t peerver_len;
uint8_t peerver_proto[4];
} __packed;
/* Mesh Peering Management Protocol */
#define IEEE80211_MESHPEERVER_PEER_OUI 0x00, 0x0f, 0xac
#define IEEE80211_MESHPEERVER_PEER_VALUE 0x2a
#define IEEE80211_MESHPEERVER_PEER { IEEE80211_MESHPEERVER_PEER_OUI, \
IEEE80211_MESHPEERVER_PEER_VALUE }
/* Abbreviated Handshake Protocol */
#define IEEE80211_MESHPEERVER_AH_OUI 0x00, 0x0f, 0xac
#define IEEE80211_MESHPEERVER_AH_VALUE 0x2b
#define IEEE80211_MESHPEERVER_AH { IEEE80211_MESHPEERVER_AH_OUI, \
IEEE80211_MESHPEERVER_AH_VALUE }
/* Peer Link Management */
struct ieee80211_meshpeer_ie {
uint8_t peer_ie; /* IEEE80211_ELEMID_MESHPEER */
uint8_t peer_len;
uint8_t peer_subtype;
uint8_t peer_proto[4]; /* Peer Management Protocol */
uint16_t peer_llinkid; /* Local Link ID */
uint16_t peer_linkid; /* Peer Link ID */
uint16_t peer_rcode;
@ -150,6 +133,16 @@ enum {
/* values 3-255 are reserved */
};
/* Mesh Peering Management Protocol */
#define IEEE80211_MESH_PEER_PROTO_OUI 0x00, 0x0f, 0xac
#define IEEE80211_MESH_PEER_PROTO_VALUE 0x2a
#define IEEE80211_MESH_PEER_PROTO { IEEE80211_MESH_PEER_PROTO_OUI, \
IEEE80211_MESH_PEER_PROTO_VALUE }
/* Abbreviated Handshake Protocol */
#define IEEE80211_MESH_PEER_PROTO_AH_OUI 0x00, 0x0f, 0xac
#define IEEE80211_MESH_PEER_PROTO_AH_VALUE 0x2b
#define IEEE80211_MESH_PEER_PROTO_AH { IEEE80211_MESH_PEER_PROTO_AH_OUI, \
IEEE80211_MESH_PEER_PROTO_AH_VALUE }
#ifdef notyet
/* Mesh Channel Switch Annoucement */
struct ieee80211_meshcsa_ie {
@ -256,11 +249,15 @@ struct ieee80211_meshprep_ie {
struct ieee80211_meshperr_ie {
uint8_t perr_ie; /* IEEE80211_ELEMID_MESHPERR */
uint8_t perr_len;
uint8_t perr_mode; /* NB: reserved */
uint8_t perr_ttl;
uint8_t perr_ndests; /* Number of Destinations */
struct {
uint8_t dest_flags;
#define IEEE80211_MESHPERR_DFLAGS_USN 0x01
#define IEEE80211_MESHPERR_DFLAGS_RC 0x02
uint8_t dest_addr[IEEE80211_ADDR_LEN];
uint32_t dest_seq; /* HWMP Sequence Number */
uint16_t dest_rcode;
} __packed perr_dests[1]; /* NB: variable size */
} __packed;
@ -310,14 +307,11 @@ enum {
};
/*
* Mesh Path Selection Action codes.
* Mesh Path Selection Action code.
*/
enum {
IEEE80211_ACTION_MESHPATH_REQ = 0,
IEEE80211_ACTION_MESHPATH_REP = 1,
IEEE80211_ACTION_MESHPATH_ERR = 2,
IEEE80211_ACTION_MESHPATH_RANN = 3,
/* 4-255 reserved */
IEEE80211_ACTION_MESHPATH_SEL = 0,
/* 1-255 reserved */
};
/*
@ -479,7 +473,6 @@ int ieee80211_mesh_register_proto_path(const
int ieee80211_mesh_register_proto_metric(const
struct ieee80211_mesh_proto_metric *);
uint8_t * ieee80211_add_meshpeerver(uint8_t *, struct ieee80211vap *);
uint8_t * ieee80211_add_meshid(uint8_t *, struct ieee80211vap *);
uint8_t * ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *);
uint8_t * ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t,