Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f444de05 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

cfg80211/mac80211: better channel handling



Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.

In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.

The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).

Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.

mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.

One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.

Note that two things are left unhandled (this is an
improvement -- not a complete fix):

 * different HT/no-HT modes

   currently you could start an HT AP and then
   connect to a non-HT network on the same channel
   which would configure the hardware for no HT;
   that can be fixed fairly easily

 * CSA

   An AP we're connected to on a virtual interface
   might indicate switching channels, and in that
   case we would follow it, regardless of how many
   other interfaces are operating; this requires
   more effort to fix but is pretty rare after all

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ac8dd506
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ static const u32 cipher_suites[] = {


static int lbs_cfg_set_channel(struct wiphy *wiphy,
	struct net_device *netdev,
	struct ieee80211_channel *chan,
	enum nl80211_channel_type channel_type)
{
+1 −0
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
}

static int orinoco_set_channel(struct wiphy *wiphy,
			struct net_device *netdev,
			struct ieee80211_channel *chan,
			enum nl80211_channel_type channel_type)
{
+2 −2
Original line number Diff line number Diff line
@@ -534,7 +534,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,

static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);

static int rndis_set_channel(struct wiphy *wiphy,
static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev,
	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);

static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
@@ -2290,7 +2290,7 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
	return deauthenticate(usbdev);
}

static int rndis_set_channel(struct wiphy *wiphy,
static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev,
	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
{
	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+13 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@
 *	%NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
 *	%NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
 *	and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
 *	However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
 *	instead, the support here is for backward compatibility only.
 * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
 *	or rename notification. Has attributes %NL80211_ATTR_WIPHY and
 *	%NL80211_ATTR_WIPHY_NAME.
@@ -329,6 +331,15 @@
 * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This
 *	command is used as an event to indicate the that a trigger level was
 *	reached.
 * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
 *	and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
 *	by %NL80211_ATTR_IFINDEX) shall operate on.
 *	In case multiple channels are supported by the device, the mechanism
 *	with which it switches channels is implementation-defined.
 *	When a monitor interface is given, it can only switch channel while
 *	no other interfaces are operating to avoid disturbing the operation
 *	of any other interfaces, and other interfaces will again take
 *	precedence when they are used.
 *
 * @NL80211_CMD_MAX: highest used command number
 * @__NL80211_CMD_AFTER_LAST: internal use
@@ -428,6 +439,8 @@ enum nl80211_commands {
	NL80211_CMD_SET_CQM,
	NL80211_CMD_NOTIFY_CQM,

	NL80211_CMD_SET_CHANNEL,

	/* add new commands above here */

	/* used to define NL80211_CMD_MAX below */
+9 −2
Original line number Diff line number Diff line
@@ -966,7 +966,11 @@ struct cfg80211_pmksa {
 *
 * @set_txq_params: Set TX queue parameters
 *
 * @set_channel: Set channel
 * @set_channel: Set channel for a given wireless interface. Some devices
 *	may support multi-channel operation (by channel hopping) so cfg80211
 *	doesn't verify much. Note, however, that the passed netdev may be
 *	%NULL as well if the user requested changing the channel for the
 *	device itself, or for a monitor interface.
 *
 * @scan: Request to do a scan. If returning zero, the scan request is given
 *	the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1095,7 +1099,7 @@ struct cfg80211_ops {
	int	(*set_txq_params)(struct wiphy *wiphy,
				  struct ieee80211_txq_params *params);

	int	(*set_channel)(struct wiphy *wiphy,
	int	(*set_channel)(struct wiphy *wiphy, struct net_device *dev,
			       struct ieee80211_channel *chan,
			       enum nl80211_channel_type channel_type);

@@ -1461,6 +1465,8 @@ struct cfg80211_cached_keys;
 * @list: (private) Used to collect the interfaces
 * @netdev: (private) Used to reference back to the netdev
 * @current_bss: (private) Used by the internal configuration code
 * @channel: (private) Used by the internal configuration code to track
 *	user-set AP, monitor and WDS channels for wireless extensions
 * @bssid: (private) Used by the internal configuration code
 * @ssid: (private) Used by the internal configuration code
 * @ssid_len: (private) Used by the internal configuration code
@@ -1507,6 +1513,7 @@ struct wireless_dev {
	struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
	struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
	struct cfg80211_internal_bss *current_bss; /* associated / joined */
	struct ieee80211_channel *channel;

	bool ps;
	int ps_timeout;
Loading