Message ID | 20200630121907.132751-13-markus.theil@tu-ilmenau.de |
---|---|
State | Changes Requested |
Headers | show |
Series | mesh: support for DFS | expand |
This patch can also be left out, but then other measures should be taken, to make most/all DFS channels available on each mesh point, in order for channel switch and CSA to work so that network does not become disconnected/ partitioned. On 6/30/20 2:19 PM, Markus Theil wrote: > This patch uses a deterministic channel on DFS channel switch > in mesh networks. Otherwise, when switching to a usable but not > available channel, no CSA can be sent and a random channel is choosen > without notification of other nodes. It is then quite likely, that > the mesh network gets disconnected. > > Fix this by using a deterministic number, based on the sha256 hash > of the mesh ID, in order to use at least a different number in each > mesh network. > > Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de> > --- > src/ap/dfs.c | 20 +++++++++++++++++++- > src/drivers/driver_nl80211.c | 4 ++++ > 2 files changed, 23 insertions(+), 1 deletion(-) > > diff --git a/src/ap/dfs.c b/src/ap/dfs.c > index 25dad3482..8f3630bf8 100644 > --- a/src/ap/dfs.c > +++ b/src/ap/dfs.c > @@ -17,6 +17,7 @@ > #include "ap_drv_ops.h" > #include "drivers/driver.h" > #include "dfs.h" > +#include "crypto/crypto.h" > > > static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) > @@ -480,9 +481,14 @@ dfs_get_valid_channel(struct hostapd_iface *iface, > int num_available_chandefs; > int chan_idx, chan_idx2; > int sec_chan_idx_80p80 = -1; > + bool is_mesh = false; > int i; > u32 _rand; > > +#ifdef CONFIG_MESH > + is_mesh = iface->mconf; > +#endif > + > wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); > *secondary_channel = 0; > *oper_centr_freq_seg0_idx = 0; > @@ -502,8 +508,20 @@ dfs_get_valid_channel(struct hostapd_iface *iface, > if (num_available_chandefs == 0) > return NULL; > > - if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) > + /* try to use deterministic channel in mesh, so that both sides > + * have a chance to switch to the same channel */ > + if (is_mesh) { > +#ifdef CONFIG_MESH > + u64 hash[4]; > + const u8 *meshid[1] = { &iface->mconf->meshid[0] }; > + const size_t meshid_len = iface->mconf->meshid_len; > + > + sha256_vector(1, meshid, &meshid_len, (u8 *)&hash[0]); > + _rand = hash[0] + hash[1] + hash[2] + hash[3]; > +#endif > + } else if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) > return NULL; > + > chan_idx = _rand % num_available_chandefs; > dfs_find_channel(iface, &chan, chan_idx, skip_radar); > if (!chan) { > diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c > index d922eda74..18521f832 100644 > --- a/src/drivers/driver_nl80211.c > +++ b/src/drivers/driver_nl80211.c > @@ -9568,6 +9568,10 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings) > if (ret) > goto error; > > + if (drv->nlmode == NL80211_IFTYPE_MESH_POINT) { > + nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS); > + } > + > /* beacon_csa params */ > beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES); > if (!beacon_csa)
On Tue, Jun 30, 2020 at 02:19:07PM +0200, Markus Theil wrote: > This patch uses a deterministic channel on DFS channel switch > in mesh networks. Otherwise, when switching to a usable but not > available channel, no CSA can be sent and a random channel is choosen > without notification of other nodes. It is then quite likely, that > the mesh network gets disconnected. > > Fix this by using a deterministic number, based on the sha256 hash > of the mesh ID, in order to use at least a different number in each > mesh network. How would this meet DFS requirements for random/even channel selection? And how would this interoperate with other implementations? I'm not convinced use of a deterministic channel is appropriate for this. The channel should still be picked randomly, but there would be need to coordinate this throughout the mesh somehow. For example, pick a DFS owner like in IBSS or provide means for somehow negotiating which randomly selected channel is used (but that may be quite challenging if there is no shared channel available for sending frames anymore).
diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 25dad3482..8f3630bf8 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -17,6 +17,7 @@ #include "ap_drv_ops.h" #include "drivers/driver.h" #include "dfs.h" +#include "crypto/crypto.h" static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) @@ -480,9 +481,14 @@ dfs_get_valid_channel(struct hostapd_iface *iface, int num_available_chandefs; int chan_idx, chan_idx2; int sec_chan_idx_80p80 = -1; + bool is_mesh = false; int i; u32 _rand; +#ifdef CONFIG_MESH + is_mesh = iface->mconf; +#endif + wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); *secondary_channel = 0; *oper_centr_freq_seg0_idx = 0; @@ -502,8 +508,20 @@ dfs_get_valid_channel(struct hostapd_iface *iface, if (num_available_chandefs == 0) return NULL; - if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) + /* try to use deterministic channel in mesh, so that both sides + * have a chance to switch to the same channel */ + if (is_mesh) { +#ifdef CONFIG_MESH + u64 hash[4]; + const u8 *meshid[1] = { &iface->mconf->meshid[0] }; + const size_t meshid_len = iface->mconf->meshid_len; + + sha256_vector(1, meshid, &meshid_len, (u8 *)&hash[0]); + _rand = hash[0] + hash[1] + hash[2] + hash[3]; +#endif + } else if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) return NULL; + chan_idx = _rand % num_available_chandefs; dfs_find_channel(iface, &chan, chan_idx, skip_radar); if (!chan) { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d922eda74..18521f832 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -9568,6 +9568,10 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings) if (ret) goto error; + if (drv->nlmode == NL80211_IFTYPE_MESH_POINT) { + nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS); + } + /* beacon_csa params */ beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES); if (!beacon_csa)
This patch uses a deterministic channel on DFS channel switch in mesh networks. Otherwise, when switching to a usable but not available channel, no CSA can be sent and a random channel is choosen without notification of other nodes. It is then quite likely, that the mesh network gets disconnected. Fix this by using a deterministic number, based on the sha256 hash of the mesh ID, in order to use at least a different number in each mesh network. Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de> --- src/ap/dfs.c | 20 +++++++++++++++++++- src/drivers/driver_nl80211.c | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-)