Date: Mon, 16 Jan 2012 09:39:35 +0100 From: Monthadar Al Jaberi <monthadar@gmail.com> To: Bernhard Schmidt <bschmidt@freebsd.org> Cc: freebsd-wireless@freebsd.org Subject: Re: 11s mesh path setup problem Message-ID: <CA%2BsBSo%2BuYa-6w8VFBMTyhWFHCNezMH5HBHJONCRvWRy6QuaCbQ@mail.gmail.com> In-Reply-To: <201201112003.44891.bschmidt@freebsd.org> References: <CA%2BsBSoJWXD5S-zvxHR_=iwh26G0bd00trR=E-jCUBD03uMrU%2BQ@mail.gmail.com> <CAJ-VmomX2NK6p%2BckB6Gc40sz0PTx7cf7NznVLH1tTPvnhmHH6A@mail.gmail.com> <201201112003.44891.bschmidt@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
On Wed, Jan 11, 2012 at 8:03 PM, Bernhard Schmidt <bschmidt@freebsd.org> wrote:
> On Wednesday 11 January 2012 18:23:29 Adrian Chadd wrote:
>> Hi!
>>
>> I've just done a bit of a code review. Here are my comments:
sorry for late answer here is a a better formated patch.
>>
>> * ether_sprintf() can't be implemented the way you've implemented it -
>> it just won't work at all in a multithreaded, concurrent environment.
>> We'll have to find an alternative way.
>>
>> Maybe something like:
>>
>> char *
>> ether_sprintf2(const u_char *ap, char *buf, int len)
>> {
>> .. do things to buf, rather than the static buf.
>> }
>>
>> Then maybe this'd work:
>>
>> char a[32], b[32];
>> IEEE80211_NOTE(..., ether_sprintf2(addr1, a, 32), ether_sprintf2(addr2, a, 32));
>>
>> does that make sense?
>
> Isn't there an example in net80211 with %D?
> printf("%6D %6D", addr1, ":", addr2, ":");
>
> The saner alternative is to call printf() multiple times, see ieee80211_dump_pkt() as an example.
But that means we have to modify for example ieee80211_note_mac function?
>
> --
> Bernhard
--
Monthadar Al Jaberi
[-- Attachment #2 --]
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 9eae683..979ebfd 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -968,9 +968,13 @@ discard:
char *
ether_sprintf(const u_char *ap)
{
- static char etherbuf[18];
- snprintf(etherbuf, sizeof (etherbuf), "%6D", ap, ":");
- return (etherbuf);
+ static char etherbuf[2][18];
+ static int i = 0;
+ char *buf;
+ snprintf(etherbuf[i], sizeof (etherbuf[0]), "%6D", ap, ":");
+ buf = etherbuf[i];
+ i = (i+1)%2;
+ return (buf);
}
/*
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 93a9e55..dfb796d 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -33,15 +33,15 @@ __FBSDID("$FreeBSD$");
/*
* IEEE 802.11s Hybrid Wireless Mesh Protocol, HWMP.
- *
+ *
* Based on March 2009, D3.0 802.11s draft spec.
*/
#include "opt_inet.h"
#include "opt_wlan.h"
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
@@ -139,9 +139,13 @@ static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] =
typedef uint32_t ieee80211_hwmp_seq;
#define HWMP_SEQ_LT(a, b) ((int32_t)((a)-(b)) < 0)
#define HWMP_SEQ_LEQ(a, b) ((int32_t)((a)-(b)) <= 0)
+#define HWMP_SEQ_EQ(a, b) ((int32_t)((a)-(b)) == 0)
#define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0)
#define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0)
+/* The longer one of the lifetime should be stored as new lifetime */
+#define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b)
+
/*
* Private extension of ieee80211_mesh_route.
*/
@@ -677,7 +681,9 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt = NULL;
struct ieee80211_mesh_route *rtorig = NULL;
- struct ieee80211_hwmp_route *hrorig;
+ struct ieee80211_mesh_route *rttarg = NULL;
+ struct ieee80211_hwmp_route *hrorig = NULL;
+ struct ieee80211_hwmp_route *hrtarg = NULL;
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
struct ieee80211_meshprep_ie prep;
@@ -692,46 +698,95 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
return;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "received PREQ, source %s", ether_sprintf(preq->preq_origaddr));
+ "received PREQ, originator %s, target %s",
+ ether_sprintf(preq->preq_origaddr), ether_sprintf(PREQ_TADDR(0)));
/*
- * Acceptance criteria: if the PREQ is not for us and
- * forwarding is disabled, discard this PREQ.
+ * Acceptance criteria: if the PREQ is not for us or not broadcast
+ * AND forwarding is disabled, discard this PREQ.
+ * XXX: need to check PROXY
*/
- if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) &&
+ if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
+ !IEEE80211_IS_MULTICAST(PREQ_TADDR(0))) &&
!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
preq->preq_origaddr, NULL, "%s", "not accepting PREQ");
return;
}
+ /*
+ * Acceptance criteria: if unicast addressed
+ * AND no valid forwarding for Target of PREQ, discard this PREQ.
+ */
+ rttarg = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
+ if(rttarg != NULL)
+ hrtarg = IEEE80211_MESH_ROUTE_PRIV(rttarg,
+ struct ieee80211_hwmp_route);
+ /* Address mode: ucast */
+ if((preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AM) == 0 &&
+ rttarg == NULL &&
+ !IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
+ preq->preq_origaddr, NULL,
+ "unicast addressed PREQ of unknown target %s",
+ ether_sprintf(PREQ_TADDR(0)));
+ return;
+ }
+
+ /* PREQ ACCEPTED */
+
rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
- if (rtorig == NULL)
+ if (rtorig == NULL) {
rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr);
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "adding originator %s",
+ ether_sprintf(preq->preq_origaddr));
+ }
if (rtorig == NULL) {
/* XXX stat */
return;
}
hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route);
- /*
- * Sequence number validation.
+
+ /* Data creation and update of forwarding information
+ * according to Table 11C-8 for originator mesh STA.
*/
- if (HWMP_SEQ_LEQ(preq->preq_id, hrorig->hr_preqid) &&
- HWMP_SEQ_LEQ(preq->preq_origseq, hrorig->hr_seq)) {
+ if(HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) ||
+ (HWMP_SEQ_EQ(preq->preq_origseq, hrorig->hr_seq) &&
+ preq->preq_metric < rtorig->rt_metric)) {
+ hrorig->hr_seq = preq->preq_origseq;
+ IEEE80211_ADDR_COPY(rtorig->rt_nexthop, wh->i_addr2);
+ rtorig->rt_metric = preq->preq_metric +
+ ms->ms_pmetric->mpm_metric(ni);
+ rtorig->rt_nhops = preq->preq_hopcount + 1;
+ rtorig->rt_lifetime = MESH_ROUTE_LIFETIME_MAX(
+ preq->preq_lifetime, rtorig->rt_lifetime);
+ /* path to orig is valid now */
+ rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
+ }else if(hrtarg != NULL &&
+ HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) &&
+ (rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREQ from %s, old seq no %u <= %u",
- ether_sprintf(preq->preq_origaddr),
- preq->preq_origseq, hrorig->hr_seq);
+ "received PREQ, originator %s", "unknown");
+ }else {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
+ preq->preq_origaddr, NULL,
+ "%s, last seen orig.seq %d, preq orig.seq %d",
+ "discarding PREQ", hrorig->hr_seq, preq->preq_origseq);
return;
}
- hrorig->hr_preqid = preq->preq_id;
- hrorig->hr_seq = preq->preq_origseq;
+
+ /*
+ * Forwarding information for transmitter mesh STA
+ * [OPTIONAL: if metric improved]
+ */
/*
* Check if the PREQ is addressed to us.
*/
if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "reply to %s", ether_sprintf(preq->preq_origaddr));
+ "reply PREP, originator %s",
+ ether_sprintf(preq->preq_origaddr));
/*
* Build and send a PREP frame.
*/
@@ -819,25 +874,29 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (preq->preq_ttl > 1 &&
preq->preq_hopcount < hs->hs_maxhops) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "forward PREQ from %s",
- ether_sprintf(preq->preq_origaddr));
+ "forward PREQ, originator %s, to %s",
+ ether_sprintf(preq->preq_origaddr),
+ ether_sprintf(rt->rt_nexthop));
/*
* Propagate the original PREQ.
+ * PREQ is unicast now to rt->rt_nexthop
*/
+ ppreq.preq_flags &=
+ ~IEEE80211_MESHPREQ_FLAGS_AM;
ppreq.preq_hopcount += 1;
ppreq.preq_ttl -= 1;
ppreq.preq_metric +=
ms->ms_pmetric->mpm_metric(ni);
/*
- * Set TO and unset RF bits because we are going
- * to send a PREP next.
+ * Set TO and unset RF bits because we are
+ * going to send a PREP next.
*/
ppreq.preq_targets[0].target_flags |=
IEEE80211_MESHPREQ_TFLAGS_TO;
ppreq.preq_targets[0].target_flags &=
~IEEE80211_MESHPREQ_TFLAGS_RF;
hwmp_send_preq(ni, vap->iv_myaddr,
- broadcastaddr, &ppreq);
+ rt->rt_nexthop, &ppreq);
}
/*
* Check if we can send an intermediate Path Reply,
@@ -870,26 +929,11 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
*/
} else if (preq->preq_ttl > 1 &&
preq->preq_hopcount < hs->hs_maxhops) {
- if (rt == NULL) {
- rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0));
- if (rt == NULL) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
- ni, "unable to add PREQ path to %s",
- ether_sprintf(PREQ_TADDR(0)));
- vap->iv_stats.is_mesh_rtaddfailed++;
- return;
- }
- }
- rt->rt_metric = preq->preq_metric;
- rt->rt_lifetime = preq->preq_lifetime;
- hrorig = IEEE80211_MESH_ROUTE_PRIV(rt,
- struct ieee80211_hwmp_route);
- hrorig->hr_seq = preq->preq_origseq;
- hrorig->hr_preqid = preq->preq_id;
-
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "forward PREQ from %s",
- ether_sprintf(preq->preq_origaddr));
+ "broadcast PREQ, originator %s, target %s",
+ ether_sprintf(preq->preq_origaddr),
+ ether_sprintf(PREQ_TADDR(0)));
+ ppreq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_AM;
ppreq.preq_hopcount += 1;
ppreq.preq_ttl -= 1;
ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni);
@@ -897,7 +941,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
&ppreq);
}
}
-
}
#undef PREQ_TFLAGS
#undef PREQ_TADDR
@@ -921,7 +964,7 @@ hwmp_send_preq(struct ieee80211_node *ni,
/*
* mesh preq action frame format
* [6] da
- * [6] sa
+ * [6] sa
* [6] addr3 = sa
* [1] action
* [1] category
@@ -943,6 +986,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = vap->iv_ifp;
struct mbuf *m, *next;
+ uint32_t metric = 0;
/*
* Acceptance criteria: if the corresponding PREQ was not generated
@@ -956,12 +1000,16 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
return;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "received PREP from %s", ether_sprintf(prep->prep_targetaddr));
+ "received PREP, originator %s, target %s",
+ ether_sprintf(prep->prep_origaddr),
+ ether_sprintf(prep->prep_targetaddr));
rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
if (rt == NULL) {
/*
* If we have no entry this could be a reply to a root PREQ.
+ * XXX: not true anymore cause we dont create entry for target
+ * when propagating PREQs like the old code did.
*/
if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
@@ -978,24 +1026,36 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
rt->rt_metric = prep->prep_metric;
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "add root path to %s nhops %d metric %d (PREP)",
+ "add root path to %s nhops %d metric %lu (PREP)",
ether_sprintf(prep->prep_targetaddr),
rt->rt_nhops, rt->rt_metric);
return;
- }
+ }
return;
}
/*
* Sequence number validation.
*/
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq)) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP from %s, old seq no %u <= %u",
- ether_sprintf(prep->prep_targetaddr),
- prep->prep_targetseq, hr->hr_seq);
- return;
+ /* Accept if route is not valid */
+ 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,
+ "discard PREP from %s, old seq no %u < %u",
+ ether_sprintf(prep->prep_targetaddr),
+ prep->prep_targetseq, hr->hr_seq);
+ return;
+ /* If same seqno compare metric */
+ }else if(HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) &&
+ prep->prep_metric > rt->rt_metric) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "discard PREP from %s, new metric %u > %u",
+ ether_sprintf(prep->prep_targetaddr),
+ prep->prep_metric, rt->rt_metric);
+ return;
+ }
}
+
hr->hr_seq = prep->prep_targetseq;
/*
* If it's NOT for us, propagate the PREP.
@@ -1003,16 +1063,13 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) {
struct ieee80211_meshprep_ie pprep; /* propagated PREP */
-
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"propagate PREP from %s",
ether_sprintf(prep->prep_targetaddr));
-
memcpy(&pprep, prep, sizeof(pprep));
pprep.prep_hopcount += 1;
pprep.prep_ttl -= 1;
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
- IEEE80211_ADDR_COPY(pprep.prep_targetaddr, vap->iv_myaddr);
hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
}
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
@@ -1022,7 +1079,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
"discard PREP for %s, route is marked PROXY",
ether_sprintf(prep->prep_targetaddr));
vap->iv_stats.is_hwmp_proxy++;
- } else if (prep->prep_origseq == hr->hr_origseq) {
+ /* 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
@@ -1031,32 +1090,35 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
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 %s, hopcount %d:%d metric %d:%d",
+ "%s path to %s, hopcount %d:%d metric %lu:%lu",
rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
- "prefer" : "update",
- ether_sprintf(prep->prep_origaddr),
- rt->rt_nhops, prep->prep_hopcount,
- rt->rt_metric, prep->prep_metric);
+ "prefer" : "update",
+ ether_sprintf(prep->prep_targetaddr),
+ rt->rt_nhops, prep->prep_hopcount + 1,
+ rt->rt_metric, metric);
IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
- rt->rt_nhops = prep->prep_hopcount;
+ rt->rt_nhops = prep->prep_hopcount + 1;
rt->rt_lifetime = prep->prep_lifetime;
- rt->rt_metric = prep->prep_metric;
+ rt->rt_metric = metric;
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
} else {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "ignore PREP for %s, hopcount %d:%d metric %d:%d",
+ "ignore PREP for %s, hopcount %d:%d metric %lu:%lu",
ether_sprintf(prep->prep_targetaddr),
rt->rt_nhops, prep->prep_hopcount,
rt->rt_metric, prep->prep_metric);
}
} else {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP for %s, wrong seqno %u != %u",
+ "discard PREP for %s, wrong orig seqno %u != %u",
ether_sprintf(prep->prep_targetaddr), prep->prep_origseq,
- hr->hr_seq);
+ hr->hr_origseq);
vap->iv_stats.is_hwmp_wrongseq++;
- }
+ }
/*
* Check for frames queued awaiting path discovery.
* XXX probably can tell exactly and avoid remove call
@@ -1064,9 +1126,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
* stuck back on the stageq because there won't be
* a path.
*/
- m = ieee80211_ageq_remove(&ic->ic_stageq,
+ m = ieee80211_ageq_remove(&ic->ic_stageq,
(struct ieee80211_node *)(uintptr_t)
- ieee80211_mac_hash(ic, rt->rt_dest));
+ ieee80211_mac_hash(ic, rt->rt_dest));
for (; m != NULL; m = next) {
next = m->m_nextpkt;
m->m_nextpkt = NULL;
@@ -1087,7 +1149,7 @@ hwmp_send_prep(struct ieee80211_node *ni,
/*
* mesh prep action frame format
* [6] da
- * [6] sa
+ * [6] sa
* [6] addr3 = sa
* [1] action
* [1] category
@@ -1146,7 +1208,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt = NULL;
struct ieee80211_hwmp_route *hr;
- struct ieee80211_meshperr_ie pperr;
+ struct ieee80211_meshperr_ie pperr;
int i, forward = 0;
/*
@@ -1165,7 +1227,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (rt == NULL)
continue;
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) &&
+ 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);
@@ -1267,7 +1329,7 @@ hwmp_send_rann(struct ieee80211_node *ni,
/*
* mesh rann action frame format
* [6] da
- * [6] sa
+ * [6] sa
* [6] addr3 = sa
* [1] action
* [1] category
@@ -1323,13 +1385,15 @@ hwmp_discover(struct ieee80211vap *vap,
/* XXX check preq retries */
sendpreq = 1;
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest,
- "start path discovery (src %s)",
+ "start path discovery (src %s), target seq %u",
m == NULL ? "<none>" : ether_sprintf(
- mtod(m, struct ether_header *)->ether_shost));
+ mtod(m, struct ether_header *)->ether_shost),
+ hr->hr_seq);
/*
* Try to discover the path for this node.
+ * Group addressed PREQ Case A
*/
- preq.preq_flags = 0;
+ preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
preq.preq_hopcount = 0;
preq.preq_ttl = ms->ms_ttl;
preq.preq_id = ++hs->hs_preqid;
@@ -1345,7 +1409,7 @@ hwmp_discover(struct ieee80211vap *vap,
if (ieee80211_hwmp_replyforward)
PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF;
PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN;
- PREQ_TSEQ(0) = 0;
+ PREQ_TSEQ(0) = hr->hr_seq;
/* XXX check return value */
hwmp_send_preq(vap->iv_bss, vap->iv_myaddr,
broadcastaddr, &preq);
@@ -1391,7 +1455,7 @@ hwmp_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
int error;
-
+
if (vap->iv_opmode != IEEE80211_M_MBSS)
return ENOSYS;
error = 0;
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 2e388ae..df7a704 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -1397,6 +1397,17 @@ setmlme_common(struct ieee80211vap *vap, int op,
IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
ieee80211_free_node(ni);
break;
+ case IEEE80211_M_MBSS:
+ IEEE80211_NODE_LOCK(nt);
+ ni = ieee80211_find_node_locked(nt, mac);
+ if (ni != NULL) {
+ ieee80211_node_leave(ni);
+ ieee80211_free_node(ni);
+ }else{
+ error = ENOENT;
+ }
+ IEEE80211_NODE_UNLOCK(nt);
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index cfffd87..6adc45a 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -336,6 +336,14 @@ mesh_rt_flush_invalid(struct ieee80211vap *vap)
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
ticks - rt->rt_crtime >= ms->ms_ppath->mpp_inact)
mesh_rt_del(ms, rt);
+ else {
+ rt->rt_lifetime -= 100; /* decrease lifetime */
+ if(rt->rt_lifetime <= 0){
+ rt->rt_flags &=
+ ~IEEE80211_MESHRT_FLAGS_VALID; /* invalidate */
+ mesh_rt_del(ms, rt);
+ }
+ }
}
MESH_RT_UNLOCK(ms);
}
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 9eae683..979ebfd 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -968,9 +968,13 @@ discard:
char *
ether_sprintf(const u_char *ap)
{
- static char etherbuf[18];
- snprintf(etherbuf, sizeof (etherbuf), "%6D", ap, ":");
- return (etherbuf);
+ static char etherbuf[2][18];
+ static int i = 0;
+ char *buf;
+ snprintf(etherbuf[i], sizeof (etherbuf[0]), "%6D", ap, ":");
+ buf = etherbuf[i];
+ i = (i+1)%2;
+ return (buf);
}
/*
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 93a9e55..58b4aff 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -33,15 +33,15 @@ __FBSDID("$FreeBSD$");
/*
* IEEE 802.11s Hybrid Wireless Mesh Protocol, HWMP.
- *
+ *
* Based on March 2009, D3.0 802.11s draft spec.
*/
#include "opt_inet.h"
#include "opt_wlan.h"
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
@@ -139,9 +139,13 @@ static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] =
typedef uint32_t ieee80211_hwmp_seq;
#define HWMP_SEQ_LT(a, b) ((int32_t)((a)-(b)) < 0)
#define HWMP_SEQ_LEQ(a, b) ((int32_t)((a)-(b)) <= 0)
+#define HWMP_SEQ_EQ(a, b) ((int32_t)((a)-(b)) == 0)
#define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0)
#define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0)
+/* The longer one of the lifetime should be stored as new lifetime */
+#define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b)
+
/*
* Private extension of ieee80211_mesh_route.
*/
@@ -256,7 +260,7 @@ hwmp_vdetach(struct ieee80211vap *vap)
callout_drain(&hs->hs_roottimer);
free(vap->iv_hwmp, M_80211_VAP);
vap->iv_hwmp = NULL;
-}
+}
int
hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
@@ -313,7 +317,7 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
LE_READ_4(&mpreq->preq_targets[0].target_seq);
hwmp_recv_preq(vap, ni, wh, &preq);
found++;
- break;
+ break;
}
case IEEE80211_ELEMID_MESHPREP:
{
@@ -677,7 +681,9 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt = NULL;
struct ieee80211_mesh_route *rtorig = NULL;
- struct ieee80211_hwmp_route *hrorig;
+ struct ieee80211_mesh_route *rttarg = NULL;
+ struct ieee80211_hwmp_route *hrorig = NULL;
+ struct ieee80211_hwmp_route *hrtarg = NULL;
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
struct ieee80211_meshprep_ie prep;
@@ -692,46 +698,95 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
return;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "received PREQ, source %s", ether_sprintf(preq->preq_origaddr));
+ "received PREQ, originator %s, target %s",
+ ether_sprintf(preq->preq_origaddr), ether_sprintf(PREQ_TADDR(0)));
/*
- * Acceptance criteria: if the PREQ is not for us and
- * forwarding is disabled, discard this PREQ.
+ * Acceptance criteria: if the PREQ is not for us or not broadcast
+ * AND forwarding is disabled, discard this PREQ.
+ * XXX: need to check PROXY
*/
- if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) &&
+ if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
+ !IEEE80211_IS_MULTICAST(PREQ_TADDR(0))) &&
!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
preq->preq_origaddr, NULL, "%s", "not accepting PREQ");
return;
}
+ /*
+ * Acceptance criteria: if unicast addressed
+ * AND no valid forwarding for Target of PREQ, discard this PREQ.
+ */
+ rttarg = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
+ if(rttarg != NULL)
+ hrtarg = IEEE80211_MESH_ROUTE_PRIV(rttarg,
+ struct ieee80211_hwmp_route);
+ /* Address mode: ucast */
+ if((preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AM) == 0 &&
+ rttarg == NULL &&
+ !IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
+ preq->preq_origaddr, NULL,
+ "unicast addressed PREQ of unknown target %s",
+ ether_sprintf(PREQ_TADDR(0)));
+ return;
+ }
+
+ /* PREQ ACCEPTED */
+
rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
- if (rtorig == NULL)
+ if (rtorig == NULL) {
rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr);
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "adding originator %s",
+ ether_sprintf(preq->preq_origaddr));
+ }
if (rtorig == NULL) {
/* XXX stat */
return;
}
hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route);
- /*
- * Sequence number validation.
+
+ /* Data creation and update of forwarding information
+ * according to Table 11C-8 for originator mesh STA.
*/
- if (HWMP_SEQ_LEQ(preq->preq_id, hrorig->hr_preqid) &&
- HWMP_SEQ_LEQ(preq->preq_origseq, hrorig->hr_seq)) {
+ if(HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) ||
+ (HWMP_SEQ_EQ(preq->preq_origseq, hrorig->hr_seq) &&
+ preq->preq_metric < rtorig->rt_metric)) {
+ hrorig->hr_seq = preq->preq_origseq;
+ IEEE80211_ADDR_COPY(rtorig->rt_nexthop, wh->i_addr2);
+ rtorig->rt_metric = preq->preq_metric +
+ ms->ms_pmetric->mpm_metric(ni);
+ rtorig->rt_nhops = preq->preq_hopcount + 1;
+ rtorig->rt_lifetime = MESH_ROUTE_LIFETIME_MAX(
+ preq->preq_lifetime, rtorig->rt_lifetime);
+ /* path to orig is valid now */
+ rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
+ }else if(hrtarg != NULL &&
+ HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) &&
+ (rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREQ from %s, old seq no %u <= %u",
- ether_sprintf(preq->preq_origaddr),
- preq->preq_origseq, hrorig->hr_seq);
+ "received PREQ, originator %s", "unknown");
+ }else {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
+ preq->preq_origaddr, NULL,
+ "%s, last seen orig.seq %d, preq orig.seq %d",
+ "discarding PREQ", hrorig->hr_seq, preq->preq_origseq);
return;
}
- hrorig->hr_preqid = preq->preq_id;
- hrorig->hr_seq = preq->preq_origseq;
+
+ /*
+ * Forwarding information for transmitter mesh STA
+ * [OPTIONAL: if metric improved]
+ */
/*
* Check if the PREQ is addressed to us.
*/
if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "reply to %s", ether_sprintf(preq->preq_origaddr));
+ "reply PREP, originator %s",
+ ether_sprintf(preq->preq_origaddr));
/*
* Build and send a PREP frame.
*/
@@ -819,25 +874,29 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (preq->preq_ttl > 1 &&
preq->preq_hopcount < hs->hs_maxhops) {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "forward PREQ from %s",
- ether_sprintf(preq->preq_origaddr));
+ "forward PREQ, originator %s, to %s",
+ ether_sprintf(preq->preq_origaddr),
+ ether_sprintf(rt->rt_nexthop));
/*
* Propagate the original PREQ.
+ * PREQ is unicast now to rt->rt_nexthop
*/
+ ppreq.preq_flags &=
+ ~IEEE80211_MESHPREQ_FLAGS_AM;
ppreq.preq_hopcount += 1;
ppreq.preq_ttl -= 1;
ppreq.preq_metric +=
ms->ms_pmetric->mpm_metric(ni);
/*
- * Set TO and unset RF bits because we are going
- * to send a PREP next.
+ * Set TO and unset RF bits because we are
+ * going to send a PREP next.
*/
ppreq.preq_targets[0].target_flags |=
IEEE80211_MESHPREQ_TFLAGS_TO;
ppreq.preq_targets[0].target_flags &=
~IEEE80211_MESHPREQ_TFLAGS_RF;
hwmp_send_preq(ni, vap->iv_myaddr,
- broadcastaddr, &ppreq);
+ rt->rt_nexthop, &ppreq);
}
/*
* Check if we can send an intermediate Path Reply,
@@ -870,26 +929,11 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
*/
} else if (preq->preq_ttl > 1 &&
preq->preq_hopcount < hs->hs_maxhops) {
- if (rt == NULL) {
- rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0));
- if (rt == NULL) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
- ni, "unable to add PREQ path to %s",
- ether_sprintf(PREQ_TADDR(0)));
- vap->iv_stats.is_mesh_rtaddfailed++;
- return;
- }
- }
- rt->rt_metric = preq->preq_metric;
- rt->rt_lifetime = preq->preq_lifetime;
- hrorig = IEEE80211_MESH_ROUTE_PRIV(rt,
- struct ieee80211_hwmp_route);
- hrorig->hr_seq = preq->preq_origseq;
- hrorig->hr_preqid = preq->preq_id;
-
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "forward PREQ from %s",
- ether_sprintf(preq->preq_origaddr));
+ "broadcast PREQ, originator %s, target %s",
+ ether_sprintf(preq->preq_origaddr),
+ ether_sprintf(PREQ_TADDR(0)));
+ ppreq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_AM;
ppreq.preq_hopcount += 1;
ppreq.preq_ttl -= 1;
ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni);
@@ -897,7 +941,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
&ppreq);
}
}
-
}
#undef PREQ_TFLAGS
#undef PREQ_TADDR
@@ -921,7 +964,7 @@ hwmp_send_preq(struct ieee80211_node *ni,
/*
* mesh preq action frame format
* [6] da
- * [6] sa
+ * [6] sa
* [6] addr3 = sa
* [1] action
* [1] category
@@ -943,6 +986,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = vap->iv_ifp;
struct mbuf *m, *next;
+ uint32_t metric = 0;
/*
* Acceptance criteria: if the corresponding PREQ was not generated
@@ -956,12 +1000,16 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
return;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "received PREP from %s", ether_sprintf(prep->prep_targetaddr));
+ "received PREP, originator %s, target %s",
+ ether_sprintf(prep->prep_origaddr),
+ ether_sprintf(prep->prep_targetaddr));
rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
if (rt == NULL) {
/*
* If we have no entry this could be a reply to a root PREQ.
+ * XXX: not true anymore cause we dont create entry for target
+ * when propagating PREQs like the old code did.
*/
if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
@@ -978,24 +1026,36 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
rt->rt_metric = prep->prep_metric;
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "add root path to %s nhops %d metric %d (PREP)",
+ "add root path to %s nhops %d metric %lu (PREP)",
ether_sprintf(prep->prep_targetaddr),
rt->rt_nhops, rt->rt_metric);
return;
- }
+ }
return;
}
/*
* Sequence number validation.
*/
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq)) {
- IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP from %s, old seq no %u <= %u",
- ether_sprintf(prep->prep_targetaddr),
- prep->prep_targetseq, hr->hr_seq);
- return;
+ /* Accept if route is not valid */
+ 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,
+ "discard PREP from %s, old seq no %u < %u",
+ ether_sprintf(prep->prep_targetaddr),
+ prep->prep_targetseq, hr->hr_seq);
+ return;
+ /* If same seqno compare metric */
+ }else if(HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) &&
+ prep->prep_metric > rt->rt_metric) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+ "discard PREP from %s, new metric %u > %u",
+ ether_sprintf(prep->prep_targetaddr),
+ prep->prep_metric, rt->rt_metric);
+ return;
+ }
}
+
hr->hr_seq = prep->prep_targetseq;
/*
* If it's NOT for us, propagate the PREP.
@@ -1003,16 +1063,13 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) {
struct ieee80211_meshprep_ie pprep; /* propagated PREP */
-
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"propagate PREP from %s",
ether_sprintf(prep->prep_targetaddr));
-
memcpy(&pprep, prep, sizeof(pprep));
pprep.prep_hopcount += 1;
pprep.prep_ttl -= 1;
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
- IEEE80211_ADDR_COPY(pprep.prep_targetaddr, vap->iv_myaddr);
hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
}
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
@@ -1022,7 +1079,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
"discard PREP for %s, route is marked PROXY",
ether_sprintf(prep->prep_targetaddr));
vap->iv_stats.is_hwmp_proxy++;
- } else if (prep->prep_origseq == hr->hr_origseq) {
+ /* 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
@@ -1031,32 +1090,35 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
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 %s, hopcount %d:%d metric %d:%d",
+ "%s path to %s, hopcount %d:%d metric %lu:%lu",
rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
- "prefer" : "update",
- ether_sprintf(prep->prep_origaddr),
- rt->rt_nhops, prep->prep_hopcount,
- rt->rt_metric, prep->prep_metric);
+ "prefer" : "update",
+ ether_sprintf(prep->prep_targetaddr),
+ rt->rt_nhops, prep->prep_hopcount + 1,
+ rt->rt_metric, metric);
IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
- rt->rt_nhops = prep->prep_hopcount;
+ rt->rt_nhops = prep->prep_hopcount + 1;
rt->rt_lifetime = prep->prep_lifetime;
- rt->rt_metric = prep->prep_metric;
+ rt->rt_metric = metric;
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
} else {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "ignore PREP for %s, hopcount %d:%d metric %d:%d",
+ "ignore PREP for %s, hopcount %d:%d metric %lu:%lu",
ether_sprintf(prep->prep_targetaddr),
rt->rt_nhops, prep->prep_hopcount,
rt->rt_metric, prep->prep_metric);
}
} else {
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "discard PREP for %s, wrong seqno %u != %u",
+ "discard PREP for %s, wrong orig seqno %u != %u",
ether_sprintf(prep->prep_targetaddr), prep->prep_origseq,
- hr->hr_seq);
+ hr->hr_origseq);
vap->iv_stats.is_hwmp_wrongseq++;
- }
+ }
/*
* Check for frames queued awaiting path discovery.
* XXX probably can tell exactly and avoid remove call
@@ -1064,9 +1126,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
* stuck back on the stageq because there won't be
* a path.
*/
- m = ieee80211_ageq_remove(&ic->ic_stageq,
+ m = ieee80211_ageq_remove(&ic->ic_stageq,
(struct ieee80211_node *)(uintptr_t)
- ieee80211_mac_hash(ic, rt->rt_dest));
+ ieee80211_mac_hash(ic, rt->rt_dest));
for (; m != NULL; m = next) {
next = m->m_nextpkt;
m->m_nextpkt = NULL;
@@ -1087,7 +1149,7 @@ hwmp_send_prep(struct ieee80211_node *ni,
/*
* mesh prep action frame format
* [6] da
- * [6] sa
+ * [6] sa
* [6] addr3 = sa
* [1] action
* [1] category
@@ -1146,7 +1208,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt = NULL;
struct ieee80211_hwmp_route *hr;
- struct ieee80211_meshperr_ie pperr;
+ struct ieee80211_meshperr_ie pperr;
int i, forward = 0;
/*
@@ -1165,7 +1227,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (rt == NULL)
continue;
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
- if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) &&
+ 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);
@@ -1267,7 +1329,7 @@ hwmp_send_rann(struct ieee80211_node *ni,
/*
* mesh rann action frame format
* [6] da
- * [6] sa
+ * [6] sa
* [6] addr3 = sa
* [1] action
* [1] category
@@ -1323,13 +1385,15 @@ hwmp_discover(struct ieee80211vap *vap,
/* XXX check preq retries */
sendpreq = 1;
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest,
- "start path discovery (src %s)",
+ "start path discovery (src %s), target seq %u",
m == NULL ? "<none>" : ether_sprintf(
- mtod(m, struct ether_header *)->ether_shost));
+ mtod(m, struct ether_header *)->ether_shost),
+ hr->hr_seq);
/*
* Try to discover the path for this node.
+ * Group addressed PREQ Case A
*/
- preq.preq_flags = 0;
+ preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
preq.preq_hopcount = 0;
preq.preq_ttl = ms->ms_ttl;
preq.preq_id = ++hs->hs_preqid;
@@ -1345,7 +1409,7 @@ hwmp_discover(struct ieee80211vap *vap,
if (ieee80211_hwmp_replyforward)
PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF;
PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN;
- PREQ_TSEQ(0) = 0;
+ PREQ_TSEQ(0) = hr->hr_seq;
/* XXX check return value */
hwmp_send_preq(vap->iv_bss, vap->iv_myaddr,
broadcastaddr, &preq);
@@ -1391,7 +1455,7 @@ hwmp_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
int error;
-
+
if (vap->iv_opmode != IEEE80211_M_MBSS)
return ENOSYS;
error = 0;
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 2e388ae..df7a704 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -1397,6 +1397,17 @@ setmlme_common(struct ieee80211vap *vap, int op,
IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
ieee80211_free_node(ni);
break;
+ case IEEE80211_M_MBSS:
+ IEEE80211_NODE_LOCK(nt);
+ ni = ieee80211_find_node_locked(nt, mac);
+ if (ni != NULL) {
+ ieee80211_node_leave(ni);
+ ieee80211_free_node(ni);
+ }else{
+ error = ENOENT;
+ }
+ IEEE80211_NODE_UNLOCK(nt);
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index cfffd87..6adc45a 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -336,6 +336,14 @@ mesh_rt_flush_invalid(struct ieee80211vap *vap)
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
ticks - rt->rt_crtime >= ms->ms_ppath->mpp_inact)
mesh_rt_del(ms, rt);
+ else {
+ rt->rt_lifetime -= 100; /* decrease lifetime */
+ if(rt->rt_lifetime <= 0){
+ rt->rt_flags &=
+ ~IEEE80211_MESHRT_FLAGS_VALID; /* invalidate */
+ mesh_rt_del(ms, rt);
+ }
+ }
}
MESH_RT_UNLOCK(ms);
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CA%2BsBSo%2BuYa-6w8VFBMTyhWFHCNezMH5HBHJONCRvWRy6QuaCbQ>
