* Added IEEE80211_ACTION_CAT_MESH in ieee80211.h as specified amendment spec;

* 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
This commit is contained in:
Adrian Chadd 2012-03-04 05:49:39 +00:00
parent 2bd5a2588e
commit bdd2a07668
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232479
6 changed files with 146 additions and 131 deletions

View File

@ -325,6 +325,7 @@ struct ieee80211_action {
#define IEEE80211_ACTION_CAT_DLS 2 /* DLS */
#define IEEE80211_ACTION_CAT_BA 3 /* BA */
#define IEEE80211_ACTION_CAT_HT 7 /* HT */
#define IEEE80211_ACTION_CAT_MESH 13 /* Mesh */
#define IEEE80211_ACTION_CAT_VENDOR 127 /* Vendor Specific */
#define IEEE80211_ACTION_HT_TXCHWIDTH 0 /* recommended xmit chan width*/

View File

@ -99,16 +99,20 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
break;
meshpl_send_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESHLMETRIC:
if (act >= N(meshlm_send_action))
break;
meshlm_send_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESHPATH:
if (act >= N(hwmp_send_action))
break;
hwmp_send_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESH:
switch (act) {
case IEEE80211_ACTION_MESH_LMETRIC:
if (act >= N(meshlm_send_action))
break;
meshlm_send_action[act] = f;
return 0;
case IEEE80211_ACTION_MESH_HWMP:
if (act >= N(hwmp_send_action))
break;
hwmp_send_action[act] = f;
return 0;
}
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (act >= N(vendor_send_action))
break;
@ -144,13 +148,17 @@ ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa)
if (act < N(meshpl_send_action))
f = meshpl_send_action[act];
break;
case IEEE80211_ACTION_CAT_MESHLMETRIC:
if (act < N(meshlm_send_action))
f = meshlm_send_action[act];
break;
case IEEE80211_ACTION_CAT_MESHPATH:
if (act < N(hwmp_send_action))
f = hwmp_send_action[act];
case IEEE80211_ACTION_CAT_MESH:
switch (act) {
case IEEE80211_ACTION_MESH_LMETRIC:
if (act < N(meshlm_send_action))
f = meshlm_send_action[act];
break;
case IEEE80211_ACTION_MESH_HWMP:
if (act < N(hwmp_send_action))
f = hwmp_send_action[act];
break;
}
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (act < N(vendor_send_action))
@ -212,16 +220,20 @@ ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f)
break;
meshpl_recv_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESHLMETRIC:
if (act >= N(meshlm_recv_action))
break;
meshlm_recv_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESHPATH:
if (act >= N(hwmp_recv_action))
break;
hwmp_recv_action[act] = f;
return 0;
case IEEE80211_ACTION_CAT_MESH:
switch (act) {
case IEEE80211_ACTION_MESH_LMETRIC:
if (act >= N(meshlm_recv_action))
break;
meshlm_recv_action[act] = f;
return 0;
case IEEE80211_ACTION_MESH_HWMP:
if (act >= N(hwmp_recv_action))
break;
hwmp_recv_action[act] = f;
return 0;
}
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (act >= N(vendor_recv_action))
break;
@ -261,13 +273,17 @@ ieee80211_recv_action(struct ieee80211_node *ni,
if (ia->ia_action < N(meshpl_recv_action))
f = meshpl_recv_action[ia->ia_action];
break;
case IEEE80211_ACTION_CAT_MESHLMETRIC:
if (ia->ia_action < N(meshlm_recv_action))
f = meshlm_recv_action[ia->ia_action];
break;
case IEEE80211_ACTION_CAT_MESHPATH:
if (ia->ia_action < N(hwmp_recv_action))
f = hwmp_recv_action[ia->ia_action];
case IEEE80211_ACTION_CAT_MESH:
switch (ia->ia_action) {
case IEEE80211_ACTION_MESH_LMETRIC:
if (ia->ia_action < N(meshlm_recv_action))
f = meshlm_recv_action[ia->ia_action];
break;
case IEEE80211_ACTION_MESH_HWMP:
if (ia->ia_action < N(hwmp_recv_action))
f = hwmp_recv_action[ia->ia_action];
break;
}
break;
case IEEE80211_ACTION_CAT_VENDOR:
if (ia->ia_action < N(vendor_recv_action))

View File

@ -220,8 +220,8 @@ ieee80211_hwmp_init(void)
/*
* Register action frame handler.
*/
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
IEEE80211_ACTION_MESHPATH_SEL, hwmp_recv_action_meshpath);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_HWMP, hwmp_recv_action_meshpath);
/* NB: default is 5 secs per spec */
mesh_proto_hwmp.mpp_inact = msecs_to_ticks(5*1000);
@ -434,8 +434,8 @@ hwmp_send_action(struct ieee80211_node *ni,
vap->iv_stats.is_tx_nobuf++;
return ENOMEM;
}
*frm++ = IEEE80211_ACTION_CAT_MESHPATH;
*frm++ = IEEE80211_ACTION_MESHPATH_SEL;
*frm++ = IEEE80211_ACTION_CAT_MESH;
*frm++ = IEEE80211_ACTION_MESH_HWMP;
switch (*ie) {
case IEEE80211_ELEMID_MESHPREQ:
frm = hwmp_add_meshpreq(frm,

View File

@ -760,6 +760,37 @@ ieee80211_parse_action(struct ieee80211_node *ni, struct mbuf *m)
break;
}
break;
case IEEE80211_ACTION_CAT_MESH:
switch (ia->ia_action) {
case IEEE80211_ACTION_MESH_LMETRIC:
/*
* XXX: verification is true only if we are using
* Airtime link metric (default)
*/
IEEE80211_VERIFY_LENGTH(efrm - frm,
sizeof(struct ieee80211_meshlmetric_ie),
return EINVAL);
break;
case IEEE80211_ACTION_MESH_HWMP:
/* verify something */
break;
case IEEE80211_ACTION_MESH_GANN:
case IEEE80211_ACTION_MESH_CC:
case IEEE80211_ACTION_MESH_MCCA_SREQ:
case IEEE80211_ACTION_MESH_MCCA_SREP:
case IEEE80211_ACTION_MESH_MCCA_AREQ:
case IEEE80211_ACTION_MESH_MCCA_ADVER:
case IEEE80211_ACTION_MESH_MCCA_TRDOWN:
case IEEE80211_ACTION_MESH_TBTT_REQ:
case IEEE80211_ACTION_MESH_TBTT_RES:
/* reject these early on, not implemented */
IEEE80211_DISCARD(vap,
IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
wh, NULL, "not implemented yet, act=0x%02X",
ia->ia_action);
return EINVAL;
}
break;
}
return 0;
}

View File

@ -122,14 +122,12 @@ static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] =
static ieee80211_recv_action_func mesh_recv_action_meshpeering_open;
static ieee80211_recv_action_func mesh_recv_action_meshpeering_confirm;
static ieee80211_recv_action_func mesh_recv_action_meshpeering_close;
static ieee80211_recv_action_func mesh_recv_action_meshlmetric_req;
static ieee80211_recv_action_func mesh_recv_action_meshlmetric_rep;
static ieee80211_recv_action_func mesh_recv_action_meshlmetric;
static ieee80211_send_action_func mesh_send_action_meshpeering_open;
static ieee80211_send_action_func mesh_send_action_meshpeering_confirm;
static ieee80211_send_action_func mesh_send_action_meshpeering_close;
static ieee80211_send_action_func mesh_send_action_meshlink_request;
static ieee80211_send_action_func mesh_send_action_meshlink_reply;
static ieee80211_send_action_func mesh_send_action_meshlmetric;
static const struct ieee80211_mesh_proto_metric mesh_metric_airtime = {
.mpm_descr = "AIRTIME",
@ -437,10 +435,8 @@ ieee80211_mesh_init(void)
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
IEEE80211_ACTION_MESHPEERING_CLOSE,
mesh_recv_action_meshpeering_close);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHLMETRIC,
IEEE80211_ACTION_MESHLMETRIC_REQ, mesh_recv_action_meshlmetric_req);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHLMETRIC,
IEEE80211_ACTION_MESHLMETRIC_REP, mesh_recv_action_meshlmetric_rep);
ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_LMETRIC, mesh_recv_action_meshlmetric);
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
IEEE80211_ACTION_MESHPEERING_OPEN,
@ -451,12 +447,9 @@ ieee80211_mesh_init(void)
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
IEEE80211_ACTION_MESHPEERING_CLOSE,
mesh_send_action_meshpeering_close);
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHLMETRIC,
IEEE80211_ACTION_MESHLMETRIC_REQ,
mesh_send_action_meshlink_request);
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHLMETRIC,
IEEE80211_ACTION_MESHLMETRIC_REP,
mesh_send_action_meshlink_reply);
ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_LMETRIC,
mesh_send_action_meshlmetric);
/*
* Register Airtime Link Metric.
@ -1861,25 +1854,24 @@ mesh_recv_action_meshpeering_close(struct ieee80211_node *ni,
* Link Metric handling.
*/
static int
mesh_recv_action_meshlmetric_req(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
uint32_t metric;
metric = mesh_airtime_calc(ni);
ieee80211_send_action(ni,
IEEE80211_ACTION_CAT_MESHLMETRIC,
IEEE80211_ACTION_MESHLMETRIC_REP,
&metric);
return 0;
}
static int
mesh_recv_action_meshlmetric_rep(struct ieee80211_node *ni,
mesh_recv_action_meshlmetric(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
const struct ieee80211_meshlmetric_ie *ie =
(const struct ieee80211_meshlmetric_ie *)
(frm+2); /* action + code */
struct ieee80211_meshlmetric_ie lm_rep;
if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
lm_rep.lm_flags = 0;
lm_rep.lm_metric = mesh_airtime_calc(ni);
ieee80211_send_action(ni,
IEEE80211_ACTION_CAT_MESH,
IEEE80211_ACTION_MESH_LMETRIC,
&lm_rep);
}
/* XXX: else do nothing for now */
return 0;
}
@ -2091,56 +2083,23 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
}
static int
mesh_send_action_meshlink_request(struct ieee80211_node *ni,
mesh_send_action_meshlmetric(struct ieee80211_node *ni,
int category, int action, void *arg0)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_meshlmetric_ie *ie = arg0;
struct mbuf *m;
uint8_t *frm;
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
"%s", "send LINK METRIC REQUEST action");
IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
ieee80211_ref_node(ni);
m = ieee80211_getmgtframe(&frm,
ic->ic_headroom + sizeof(struct ieee80211_frame),
sizeof(uint16_t) /* action+category */
);
if (m != NULL) {
/*
* mesh link metric request
* [1] category
* [1] action
*/
*frm++ = category;
*frm++ = action;
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
return mesh_send_action(ni, m);
if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
ni, "%s", "send LINK METRIC REQUEST action");
} else {
vap->iv_stats.is_tx_nobuf++;
ieee80211_free_node(ni);
return ENOMEM;
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
ni, "send LINK METRIC REPLY action: metric 0x%x",
ie->lm_metric);
}
}
static int
mesh_send_action_meshlink_reply(struct ieee80211_node *ni,
int category, int action, void *args0)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
uint32_t *metric = args0;
struct mbuf *m;
uint8_t *frm;
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
"send LINK METRIC REPLY action: metric 0x%x", *metric);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
@ -2148,19 +2107,20 @@ mesh_send_action_meshlink_reply(struct ieee80211_node *ni,
m = ieee80211_getmgtframe(&frm,
ic->ic_headroom + sizeof(struct ieee80211_frame),
sizeof(uint16_t) /* action+category */
+ sizeof(struct ieee80211_meshlmetric_ie)
sizeof(uint16_t) + /* action+category */
sizeof(struct ieee80211_meshlmetric_ie)
);
if (m != NULL) {
/*
* mesh link metric reply
* mesh link metric
* [1] category
* [1] action
* [tlv] mesh link metric
*/
*frm++ = category;
*frm++ = action;
frm = ieee80211_add_meshlmetric(frm, *metric);
frm = ieee80211_add_meshlmetric(frm,
ie->lm_flags, ie->lm_metric);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
return mesh_send_action(ni, m);
} else {
@ -2505,10 +2465,11 @@ mesh_airtime_calc(struct ieee80211_node *ni)
* Add a Mesh Link Metric report IE to a frame.
*/
uint8_t *
ieee80211_add_meshlmetric(uint8_t *frm, uint32_t metric)
ieee80211_add_meshlmetric(uint8_t *frm, uint8_t flags, uint32_t metric)
{
*frm++ = IEEE80211_ELEMID_MESHLINK;
*frm++ = 4;
*frm++ = 5;
*frm++ = flags;
ADDWORD(frm, metric);
return frm;
}

View File

@ -119,8 +119,14 @@ struct ieee80211_meshid_ie {
/* Link Metric Report */
struct ieee80211_meshlmetric_ie {
uint8_t lm_ie; /* IEEE80211_ELEMID_MESHLINK */
uint8_t lm_ie; /* IEEE80211_ACTION_MESH_LMETRIC */
uint8_t lm_len;
uint8_t lm_flags;
#define IEEE80211_MESH_LMETRIC_FLAGS_REQ 0x01 /* Request */
/*
* XXX: this field should be variable in size and depend on
* the active active path selection metric identifier
*/
uint32_t lm_metric;
#define IEEE80211_MESHLMETRIC_INITIALVAL 0
} __packed;
@ -307,8 +313,7 @@ struct ieee80211_meshpuc_ie {
* 802.11s Action Frames
*/
#define IEEE80211_ACTION_CAT_MESHPEERING 30 /* XXX Linux */
#define IEEE80211_ACTION_CAT_MESHLMETRIC 13
#define IEEE80211_ACTION_CAT_MESHPATH 32 /* XXX Linux */
/* XXX: these need to be looked into */
#define IEEE80211_ACTION_CAT_INTERWORK 15
#define IEEE80211_ACTION_CAT_RESOURCE 16
#define IEEE80211_ACTION_CAT_PROXY 17
@ -324,20 +329,21 @@ enum {
};
/*
* Mesh Path Selection Action code.
* Mesh Action code.
*/
enum {
IEEE80211_ACTION_MESHPATH_SEL = 0,
/* 1-255 reserved */
};
/*
* Mesh Link Metric Action codes.
*/
enum {
IEEE80211_ACTION_MESHLMETRIC_REQ = 0, /* Link Metric Request */
IEEE80211_ACTION_MESHLMETRIC_REP = 1, /* Link Metric Report */
/* 2-255 reserved */
IEEE80211_ACTION_MESH_LMETRIC = 0, /* Mesh Link Metric Report */
IEEE80211_ACTION_MESH_HWMP = 1, /* HWMP Mesh Path Selection */
IEEE80211_ACTION_MESH_GANN = 2, /* Gate Announcement */
IEEE80211_ACTION_MESH_CC = 3, /* Congestion Control */
IEEE80211_ACTION_MESH_MCCA_SREQ = 4, /* MCCA Setup Request */
IEEE80211_ACTION_MESH_MCCA_SREP = 5, /* MCCA Setup Reply */
IEEE80211_ACTION_MESH_MCCA_AREQ = 6, /* MCCA Advertisement Req. */
IEEE80211_ACTION_MESH_MCCA_ADVER =7, /* MCCA Advertisement */
IEEE80211_ACTION_MESH_MCCA_TRDOWN = 8, /* MCCA Teardown */
IEEE80211_ACTION_MESH_TBTT_REQ = 9, /* TBTT Adjustment Request */
IEEE80211_ACTION_MESH_TBTT_RES = 10, /* TBTT Adjustment Response */
/* 11-255 reserved */
};
/*
@ -496,7 +502,7 @@ 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,
uint16_t);
uint8_t * ieee80211_add_meshlmetric(uint8_t *, uint32_t);
uint8_t * ieee80211_add_meshlmetric(uint8_t *, uint8_t, uint32_t);
void ieee80211_mesh_node_init(struct ieee80211vap *,
struct ieee80211_node *);