* @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding
* or forwarding entity (default is TRUE - forwarding entity)
*
+ * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the
+ * threshold for average signal strength of candidate station to establish
+ * a peer link.
+ *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
NL80211_MESHCONF_FORWARDING,
+ NL80211_MESHCONF_RSSI_THRESHOLD,
/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
* Still keeping the same nomenclature to be in sync with the spec. */
bool dot11MeshGateAnnouncementProtocol;
bool dot11MeshForwarding;
+ s32 rssi_threshold;
};
/**
}
if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
+ if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
+ /* our RSSI threshold implementation is supported only for
+ * devices that report signal in dBm.
+ */
+ if (!(sdata->local->hw.flags & IEEE80211_HW_SIGNAL_DBM))
+ return -ENOTSUPP;
+ conf->rssi_threshold = nconf->rssi_threshold;
+ }
return 0;
}
IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
+IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
#endif
MESHPARAMS_ADD(dot11MeshHWMPRootMode);
MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
+ MESHPARAMS_ADD(rssi_threshold);
#undef MESHPARAMS_ADD
}
#endif
#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
+#define sta_meets_rssi_threshold(sta, sdata) \
+ (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
+ (s8) -ewma_read(&sta->avg_signal) > \
+ sdata->u.mesh.mshcfg.rssi_threshold)
+
enum plink_event {
PLINK_UNDEFINED,
OPN_ACPT,
if (mesh_peer_accepts_plinks(elems) &&
sta->plink_state == NL80211_PLINK_LISTEN &&
sdata->u.mesh.accepting_plinks &&
- sdata->u.mesh.mshcfg.auto_open_plinks)
+ sdata->u.mesh.mshcfg.auto_open_plinks &&
+ sta_meets_rssi_threshold(sta, sdata))
mesh_plink_open(sta);
rcu_read_unlock();
return;
}
+ if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
+ !sta_meets_rssi_threshold(sta, sdata)) {
+ mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
+ sta->sta.addr);
+ rcu_read_unlock();
+ return;
+ }
+
if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
rcu_read_unlock();
#define MESH_PERR_MIN_INT 100
#define MESH_DIAM_TRAVERSAL_TIME 50
+#define MESH_RSSI_THRESHOLD 0
+
/*
* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
* before timing out. This way it will remain ACTIVE and no data frames
.dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
.dot11MeshGateAnnouncementProtocol = false,
.dot11MeshForwarding = true,
+ .rssi_threshold = MESH_RSSI_THRESHOLD,
};
const struct mesh_setup default_mesh_setup = {
cur_params.dot11MeshGateAnnouncementProtocol);
NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING,
cur_params.dot11MeshForwarding);
+ NLA_PUT_U32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
+ cur_params.rssi_threshold);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
[NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
[NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
+ [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
};
static const struct nla_policy
nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding,
mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
+ mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
if (mask_out)
*mask_out = mask;