summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_hwmp.c
diff options
context:
space:
mode:
authormonthadar <monthadar@FreeBSD.org>2012-05-01 15:56:26 +0000
committermonthadar <monthadar@FreeBSD.org>2012-05-01 15:56:26 +0000
commit66eb02c1dc5e68076bf50a497792f81f047e74ea (patch)
tree7789c09019e4a96470216c276b33223cdf9db176 /sys/net80211/ieee80211_hwmp.c
parent661f0aa0b474eeb0e2188d7c75ce16dbe34a0229 (diff)
downloadFreeBSD-src-66eb02c1dc5e68076bf50a497792f81f047e74ea.zip
FreeBSD-src-66eb02c1dc5e68076bf50a497792f81f047e74ea.tar.gz
Mesh forwarding with proxy support.
* 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
Diffstat (limited to 'sys/net80211/ieee80211_hwmp.c')
-rw-r--r--sys/net80211/ieee80211_hwmp.c184
1 files changed, 121 insertions, 63 deletions
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 3be6551..334399e 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -143,6 +143,8 @@ typedef uint32_t ieee80211_hwmp_seq;
#define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0)
#define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0)
+#define HWMP_SEQ_MAX(a, b) (a > b ? a : b)
+
/*
* Private extension of ieee80211_mesh_route.
*/
@@ -866,7 +868,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
const struct ieee80211_frame *wh, const struct ieee80211_meshpreq_ie *preq)
{
struct ieee80211_mesh_state *ms = vap->iv_mesh;
- struct ieee80211_mesh_route *rt = NULL;
+ struct ieee80211_mesh_route *rt = NULL; /* pro-active code */
struct ieee80211_mesh_route *rtorig = NULL;
struct ieee80211_mesh_route *rttarg = NULL;
struct ieee80211_hwmp_route *hrorig = NULL;
@@ -963,31 +965,44 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
/*
* Check if the PREQ is addressed to us.
+ * or a Proxy currently supplied by us.
*/
- if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "reply to %6D", preq->preq_origaddr, ":");
+ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
+ (rttarg != NULL &&
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY &&
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
/*
- * Build and send a PREP frame.
+ * When we are the target we shall update our own HWMP seq
+ * number with max of (current and preq->seq) + 1
*/
+ hs->hs_seq = HWMP_SEQ_MAX(hs->hs_seq, PREQ_TSEQ(0)) + 1;
+
prep.prep_flags = 0;
+ if (rttarg != NULL && /* if NULL it means we are the target */
+ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "reply for proxy %6D", rttarg->rt_dest, ":");
+ prep.prep_flags |= IEEE80211_MESHPREP_FLAGS_AE;
+ IEEE80211_ADDR_COPY(prep.prep_target_ext_addr,
+ rttarg->rt_dest);
+ /* update proxy seqno to HWMP seqno */
+ rttarg->rt_ext_seq = hs->hs_seq;
+ }
+ /*
+ * Build and send a PREP frame.
+ */
prep.prep_hopcount = 0;
prep.prep_ttl = ms->ms_ttl;
IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr);
- prep.prep_targetseq = ++hs->hs_seq;
+ prep.prep_targetseq = hs->hs_seq;
prep.prep_lifetime = preq->preq_lifetime;
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr);
prep.prep_origseq = preq->preq_origseq;
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "reply to %6D", preq->preq_origaddr, ":");
hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep);
- /*
- * Build the reverse path, if we don't have it already.
- */
- rt = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
- if (rt == NULL)
- hwmp_discover(vap, preq->preq_origaddr, NULL);
- else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
- hwmp_discover(vap, rt->rt_dest, NULL);
return;
}
/*
@@ -1179,15 +1194,19 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
struct ieee80211_mesh_route *rt = NULL;
+ struct ieee80211_mesh_route *rtorig = NULL;
+ struct ieee80211_mesh_route *rtext = NULL;
struct ieee80211_hwmp_route *hr;
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = vap->iv_ifp;
struct mbuf *m, *next;
uint32_t metric = 0;
+ const uint8_t *addr;
/*
- * Acceptance criteria: if the corresponding PREQ was not generated
- * by us and forwarding is disabled, discard this PREP.
+ * Acceptance criteria: If the corresponding PREP was not generated
+ * by us or generated by an external mac that is proxied by us
+ * and forwarding is disabled, discard this PREP.
*/
if (ni == vap->iv_bss ||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
@@ -1195,10 +1214,21 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
return;
+ rtorig = ieee80211_mesh_rt_find(vap, prep->prep_origaddr);
+ if (rtorig != NULL &&
+ !(rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "received PREP(%u) for an orig(%6D) not proxied by us",
+ prep->prep_origseq, prep->prep_origaddr, ":");
+ return;
+ }
+
+ /* PREP ACCEPTED */
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"received PREP from %6D", prep->prep_targetaddr, ":");
+#if 0
rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
if (rt == NULL) {
/*
@@ -1228,10 +1258,30 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
}
return;
}
+#endif
+
/*
- * Sequence number validation.
+ * If accepted shall create or update the active forwarding information
+ * it maintains for the target mesh STA of the PREP (according to the
+ * rules defined in 13.10.8.4). If the conditions for creating or
+ * updating the forwarding information have not been met in those
+ * rules, no further steps are applied to the PREP.
+ * [OPTIONAL]: update forwarding information to TA if metric improves.
*/
+ rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
+ if (rt == NULL) {
+ rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
+ if (rt == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "unable to add PREP path to %6D",
+ prep->prep_targetaddr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
+ }
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
+ /* update path metric */
+ metric = prep->prep_metric + ms->ms_pmetric->mpm_metric(ni);
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
if (HWMP_SEQ_LT(prep->prep_targetseq, hr->hr_seq)) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
@@ -1240,7 +1290,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
prep->prep_targetseq, hr->hr_seq);
return;
} else if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) &&
- prep->prep_metric > rt->rt_metric) {
+ metric > rt->rt_metric) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"discard PREP from %6D, new metric %u > %u",
prep->prep_targetaddr, ":",
@@ -1249,7 +1299,21 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
}
}
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "%s path to %6D, hopcount %d:%d metric %d:%d",
+ rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+ "prefer" : "update",
+ prep->prep_targetaddr, ":",
+ rt->rt_nhops, prep->prep_hopcount,
+ rt->rt_metric, metric);
+
hr->hr_seq = prep->prep_targetseq;
+ IEEE80211_ADDR_COPY(rt->rt_nexthop, ni->ni_macaddr);
+ rt->rt_metric = metric;
+ rt->rt_nhops = prep->prep_hopcount + 1;
+ ieee80211_mesh_rt_update(rt, prep->prep_lifetime);
+ rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; /* mark valid */
+
/*
* If it's NOT for us, propagate the PREP.
*/
@@ -1265,53 +1329,45 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
pprep.prep_ttl -= 1;
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
+
+ /* may store target external address if recevied PREP w/ AE */
+ /* precursor list for the Target Mesh STA Address is updated */
}
- hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
- /* NB: never clobber a proxy entry */;
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP for %6D, route is marked PROXY",
- prep->prep_targetaddr, ":");
- vap->iv_stats.is_hwmp_proxy++;
- /* NB: first path discovery always fails */
- } else if (hr->hr_origseq == 0 ||
- prep->prep_origseq == hr->hr_origseq) {
- /*
- * Check if we already have a path to this node.
- * If we do, check if this path reply contains a
- * better route.
- */
- if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
- (prep->prep_hopcount < rt->rt_nhops ||
- prep->prep_metric < rt->rt_metric)) {
- hr->hr_origseq = prep->prep_origseq;
- metric = prep->prep_metric +
- ms->ms_pmetric->mpm_metric(ni);
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "%s path to %6D, hopcount %d:%d metric %d:%d",
- rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
- "prefer" : "update",
- prep->prep_origaddr, ":",
- rt->rt_nhops, prep->prep_hopcount,
- rt->rt_metric, prep->prep_metric);
- IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
- rt->rt_nhops = prep->prep_hopcount + 1;
- ieee80211_mesh_rt_update(rt, prep->prep_lifetime);
- rt->rt_metric = metric;
- rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
- } else {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "ignore PREP for %6D, hopcount %d:%d metric %d:%d",
- prep->prep_targetaddr, ":",
- rt->rt_nhops, prep->prep_hopcount,
- rt->rt_metric, prep->prep_metric);
+ /* check if we received a PREP for a proxy address */
+ else if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE) {
+ rtext = ieee80211_mesh_rt_find(vap,
+ prep->prep_target_ext_addr);
+ if (rtext == NULL) {
+ rtext = ieee80211_mesh_rt_add(vap,
+ prep->prep_target_ext_addr);
+ if (rtext == NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "unable to add PREP path to proxy %6D",
+ prep->prep_targetaddr, ":");
+ vap->iv_stats.is_mesh_rtaddfailed++;
+ return;
+ }
}
- } else {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP for %6D, wrong orig seqno %u != %u",
- prep->prep_targetaddr, ":", prep->prep_origseq,
- hr->hr_origseq);
- vap->iv_stats.is_hwmp_wrongseq++;
+ "%s path to %6D, hopcount %d:%d metric %d:%d",
+ rtext->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+ "prefer" : "update",
+ prep->prep_target_ext_addr, ":",
+ rtext->rt_nhops, prep->prep_hopcount,
+ rtext->rt_metric, metric);
+
+ rtext->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY |
+ IEEE80211_MESHRT_FLAGS_VALID;
+ IEEE80211_ADDR_COPY(rtext->rt_dest,
+ prep->prep_target_ext_addr);
+ IEEE80211_ADDR_COPY(rtext->rt_mesh_gate,
+ prep->prep_targetaddr);
+ IEEE80211_ADDR_COPY(rtext->rt_nexthop, wh->i_addr2);
+ rtext->rt_metric = metric;
+ rtext->rt_lifetime = prep->prep_lifetime;
+ rtext->rt_nhops = prep->prep_hopcount + 1;
+ rtext->rt_ext_seq = prep->prep_origseq; /* proxy seq */
+ /* proxy entries have no HWMP priv data, nullify them to be sure? */
}
/*
* Check for frames queued awaiting path discovery.
@@ -1320,9 +1376,11 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
* stuck back on the stageq because there won't be
* a path.
*/
+ addr = prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE ?
+ prep->prep_target_ext_addr : prep->prep_targetaddr;
m = ieee80211_ageq_remove(&ic->ic_stageq,
(struct ieee80211_node *)(uintptr_t)
- ieee80211_mac_hash(ic, rt->rt_dest));
+ ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */
for (; m != NULL; m = next) {
next = m->m_nextpkt;
m->m_nextpkt = NULL;
OpenPOWER on IntegriCloud