2017-01-28 00:01:58

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 1/3] mac80211: fix mesh moving average stuck

As moving average is not considering fractional part after
certain ratio, it will stuck at the same state. For example
with current values, moving average stuck at 96 and it will
not move forward. Fortunately current threshold is matching
against 95%. If thresold is increased more than 96, mesh path
never be deactivated under worst case. Fix failure average
movement by bumping up average at stuck state.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/mesh_hwmp.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index b747c9645e43..f0aa1da15bd0 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -300,6 +300,7 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
{
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ u32 fail_avg = sta->mesh->fail_avg;
int failed;

if (!ieee80211_is_data(hdr->frame_control))
@@ -308,8 +309,17 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);

/* moving average, scaled to 100 */
- sta->mesh->fail_avg =
- ((80 * sta->mesh->fail_avg + 5) / 100 + 20 * failed);
+ fail_avg = ((80 * fail_avg + 5) / 100 + 20 * failed);
+
+ /* bump up fail average since fractional part of average is ignored.
+ * Otherwise fail average always stuck at the same level and
+ * never moves forward.
+ */
+ if (fail_avg && fail_avg == sta->mesh->fail_avg)
+ fail_avg++;
+
+ sta->mesh->fail_avg = fail_avg;
+
if (sta->mesh->fail_avg > 95)
mesh_plink_broken(sta);
}
--
1.9.1


2017-01-31 19:47:56

by Thomas Pedersen

[permalink] [raw]
Subject: Re: [PATCH 3/3] mac80211: clear failure average upon mesh path deactivation

On Tue, Jan 31, 2017 at 11:33 AM, Rajkumar Manoharan
<[email protected]> wrote:
> On 2017-01-31 09:51, Thomas Pedersen wrote:
>>
>> Hi Rajkumar,
>>
>> Thanks this looks good, but..
>>
>> On Fri, Jan 27, 2017 at 4:01 PM, Rajkumar Manoharan
>> <[email protected]> wrote:
>>>
>>> Mesh moving average should be cleared, whenever mesh paths
>>> to the given station are deactivated due to bad link. This will
>>> give enough room to analysis more tx status than retaining the
>>> current average.
>>>
> [...]
>>>
>>> ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
>>> if (ret)
>>> @@ -535,8 +536,11 @@ void mesh_plink_broken(struct sta_info *sta)
>>> sdata->u.mesh.mshcfg.element_ttl,
>>> mpath->dst, mpath->sn,
>>> WLAN_REASON_MESH_PATH_DEST_UNREACHABLE,
>>> bcast);
>>> + paths_deactivated = true;
>>> }
>>> }
>>> + if (paths_deactivated)
>>> + sta->mesh->fail_avg = 0;
>>
>>
>> .. why this indirection? Just reset mesh->fail_avg unconditionally in
>> this function?
>>
> Hmm... As fixed paths are not affected, resetting fail_avg for fixed path
> may give
> wrong metric. no?

I don't think setting fail_avg = 0 will affect existing fixed mpath
code. Anyway metrics should not
affect whether a fixed mpath is chosen.

--
thomas

2017-01-31 19:33:55

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 3/3] mac80211: clear failure average upon mesh path deactivation

On 2017-01-31 09:51, Thomas Pedersen wrote:
> Hi Rajkumar,
>
> Thanks this looks good, but..
>
> On Fri, Jan 27, 2017 at 4:01 PM, Rajkumar Manoharan
> <[email protected]> wrote:
>> Mesh moving average should be cleared, whenever mesh paths
>> to the given station are deactivated due to bad link. This will
>> give enough room to analysis more tx status than retaining the
>> current average.
>>
[...]
>> ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
>> if (ret)
>> @@ -535,8 +536,11 @@ void mesh_plink_broken(struct sta_info *sta)
>> sdata->u.mesh.mshcfg.element_ttl,
>> mpath->dst, mpath->sn,
>>
>> WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
>> + paths_deactivated = true;
>> }
>> }
>> + if (paths_deactivated)
>> + sta->mesh->fail_avg = 0;
>
> .. why this indirection? Just reset mesh->fail_avg unconditionally in
> this function?
>
Hmm... As fixed paths are not affected, resetting fail_avg for fixed
path may give
wrong metric. no?

-Rajkumar

2017-01-28 00:02:25

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 3/3] mac80211: clear failure average upon mesh path deactivation

Mesh moving average should be cleared, whenever mesh paths
to the given station are deactivated due to bad link. This will
give enough room to analysis more tx status than retaining the
current average.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/mesh_pathtbl.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index f0e6175a9821..208ad36c0a7f 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -510,6 +510,7 @@ void mesh_plink_broken(struct sta_info *sta)
struct mesh_path *mpath;
struct rhashtable_iter iter;
int ret;
+ bool paths_deactivated = false;

ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
if (ret)
@@ -535,8 +536,11 @@ void mesh_plink_broken(struct sta_info *sta)
sdata->u.mesh.mshcfg.element_ttl,
mpath->dst, mpath->sn,
WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
+ paths_deactivated = true;
}
}
+ if (paths_deactivated)
+ sta->mesh->fail_avg = 0;
out:
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
--
1.9.1

2017-01-31 19:54:28

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 3/3] mac80211: clear failure average upon mesh path deactivation

On 2017-01-31 11:46, Thomas Pedersen wrote:
> On Tue, Jan 31, 2017 at 11:33 AM, Rajkumar Manoharan wrote:
>> On 2017-01-31 09:51, Thomas Pedersen wrote:
>>>
[...]
>>>> + if (paths_deactivated)
>>>> + sta->mesh->fail_avg = 0;
>>>
>>>
>>> .. why this indirection? Just reset mesh->fail_avg unconditionally in
>>> this function?
>>>
>> Hmm... As fixed paths are not affected, resetting fail_avg for fixed
>> path
>> may give
>> wrong metric. no?
>
> I don't think setting fail_avg = 0 will affect existing fixed mpath
> code. Anyway metrics should not
> affect whether a fixed mpath is chosen.
>
Great. Will remove conditional check. Thanks for your feedback Thomas.

-Rajkumar

2017-01-31 17:51:36

by Thomas Pedersen

[permalink] [raw]
Subject: Re: [PATCH 3/3] mac80211: clear failure average upon mesh path deactivation

Hi Rajkumar,

Thanks this looks good, but..

On Fri, Jan 27, 2017 at 4:01 PM, Rajkumar Manoharan
<[email protected]> wrote:
> Mesh moving average should be cleared, whenever mesh paths
> to the given station are deactivated due to bad link. This will
> give enough room to analysis more tx status than retaining the
> current average.
>
> Signed-off-by: Rajkumar Manoharan <[email protected]>
> ---
> net/mac80211/mesh_pathtbl.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
> index f0e6175a9821..208ad36c0a7f 100644
> --- a/net/mac80211/mesh_pathtbl.c
> +++ b/net/mac80211/mesh_pathtbl.c
> @@ -510,6 +510,7 @@ void mesh_plink_broken(struct sta_info *sta)
> struct mesh_path *mpath;
> struct rhashtable_iter iter;
> int ret;
> + bool paths_deactivated = false;
>
> ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
> if (ret)
> @@ -535,8 +536,11 @@ void mesh_plink_broken(struct sta_info *sta)
> sdata->u.mesh.mshcfg.element_ttl,
> mpath->dst, mpath->sn,
> WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
> + paths_deactivated = true;
> }
> }
> + if (paths_deactivated)
> + sta->mesh->fail_avg = 0;

.. why this indirection? Just reset mesh->fail_avg unconditionally in
this function?


--
thomas

2017-01-28 00:02:15

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 2/3] mac80211: Make mesh failure moving average configurable

Currently mesh moving fail average is calculated based on constant
weight factor. In worst case moving average reaches threshold by
considering 16 msdu tx ack status and deactivates mesh path. Having
a constant weight factor might not be suitable for all environments.
So make it tunable parameter and also lower default weight to 10 so
that mesh broken link calculation will consider more packet status
(32 msdus ack status) before dropping mesh path.

In OTA 2-hop topolgy (MP1 <-> MP2 <-> MP3), while running TCP traffic
of window size of 2M where each nodes are operating in VHT80 mode,
mesh path between forwarding node (MP2) and border nodes (MP1/MP3) is
deactivated more often when average weight is 20.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/debugfs_netdev.c | 27 +++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mesh.c | 1 +
net/mac80211/mesh.h | 3 +++
net/mac80211/mesh_hwmp.c | 4 +++-
5 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 8f5fff8b2040..3923401a85dd 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -586,6 +586,32 @@ static ssize_t ieee80211_if_parse_tsf(
#ifdef CONFIG_MAC80211_MESH
IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);

+static ssize_t ieee80211_if_fmt_fail_avg_weight(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+ return snprintf(buf, buflen, "%d\n", sdata->u.mesh.fail_avg_weight);
+}
+
+static ssize_t ieee80211_if_parse_fail_avg_weight(
+ struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
+{
+ u8 val;
+ int ret;
+
+ ret = kstrtou8(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val > 100)
+ return -ERANGE;
+
+ sdata->u.mesh.fail_avg_weight = val;
+
+ return buflen;
+}
+
+IEEE80211_IF_FILE_RW(fail_avg_weight);
+
/* Mesh stats attributes */
IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
@@ -711,6 +737,7 @@ static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD_MODE(tsf, 0600);
DEBUGFS_ADD_MODE(estab_plinks, 0400);
+ DEBUGFS_ADD_MODE(fail_avg_weight, 0600);
}

static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 159a1a733725..30babcea3e06 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -711,6 +711,7 @@ struct ieee80211_if_mesh {
struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
int mpp_paths_generation;
+ u8 fail_avg_weight;
};

#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9c23172feba0..491fd76f91bd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1368,6 +1368,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
ifmsh->last_preq = jiffies;
ifmsh->next_perr = jiffies;
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
+ ifmsh->fail_avg_weight = MESH_FAIL_AVG_WEIGHT;
/* Allocate all mesh structures when creating the first mesh interface. */
if (!mesh_allocated)
ieee80211s_init();
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 7e5f271e3c30..887746022cc6 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -185,6 +185,9 @@ struct mesh_rmc {
/* Number of frames buffered per destination for unresolved destinations */
#define MESH_FRAME_QUEUE_LEN 10

+/* Moving failure average weight of mesh peer link (in percent) */
+#define MESH_FAIL_AVG_WEIGHT 10
+
/* Public interfaces */
/* Various */
int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index f0aa1da15bd0..61a824eb2c73 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -301,6 +301,7 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u32 fail_avg = sta->mesh->fail_avg;
+ u8 fail_avg_weight = sta->sdata->u.mesh.fail_avg_weight;
int failed;

if (!ieee80211_is_data(hdr->frame_control))
@@ -309,7 +310,8 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);

/* moving average, scaled to 100 */
- fail_avg = ((80 * fail_avg + 5) / 100 + 20 * failed);
+ fail_avg = (((100 - fail_avg_weight) * fail_avg + 5) / 100 +
+ fail_avg_weight * failed);

/* bump up fail average since fractional part of average is ignored.
* Otherwise fail average always stuck at the same level and
--
1.9.1