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

Commit 6e19bc4b authored by Dmitry Shmidt's avatar Dmitry Shmidt Committed by Johannes Berg
Browse files

nl80211: allow BSS data to include CLOCK_BOOTTIME timestamp



For location and connectivity services, userspace would often like
to know the time when the BSS was last seen. The current "last seen"
value is calculated in a way that makes it less useful, especially
if the system suspended in the meantime.

Add the ability for the driver to report a real CLOCK_BOOTTIME stamp
that can then be reported to userspace (if present).

Drivers wishing to use this must be converted to the new API to call
cfg80211_inform_bss_data() or cfg80211_inform_bss_frame_data(). They
need to ensure the reported value is accurate enough even when the
frame might have been buffered in the device (e.g. firmware.)

Signed-off-by: default avatarDmitry Shmidt <dimitrysh@google.com>
[modified to use struct, inlines]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 93f0490e
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -154,8 +154,9 @@
!Finclude/net/cfg80211.h cfg80211_scan_request
!Finclude/net/cfg80211.h cfg80211_scan_request
!Finclude/net/cfg80211.h cfg80211_scan_done
!Finclude/net/cfg80211.h cfg80211_scan_done
!Finclude/net/cfg80211.h cfg80211_bss
!Finclude/net/cfg80211.h cfg80211_bss
!Finclude/net/cfg80211.h cfg80211_inform_bss_width_frame
!Finclude/net/cfg80211.h cfg80211_inform_bss
!Finclude/net/cfg80211.h cfg80211_inform_bss_width
!Finclude/net/cfg80211.h cfg80211_inform_bss_frame_data
!Finclude/net/cfg80211.h cfg80211_inform_bss_data
!Finclude/net/cfg80211.h cfg80211_unlink_bss
!Finclude/net/cfg80211.h cfg80211_unlink_bss
!Finclude/net/cfg80211.h cfg80211_find_ie
!Finclude/net/cfg80211.h cfg80211_find_ie
!Finclude/net/cfg80211.h ieee80211_bss_get_ie
!Finclude/net/cfg80211.h ieee80211_bss_get_ie
+76 −19
Original line number Original line Diff line number Diff line
@@ -1575,6 +1575,26 @@ enum cfg80211_signal_type {
	CFG80211_SIGNAL_TYPE_UNSPEC,
	CFG80211_SIGNAL_TYPE_UNSPEC,
};
};


/**
 * struct cfg80211_inform_bss - BSS inform data
 * @chan: channel the frame was received on
 * @scan_width: scan width that was used
 * @signal: signal strength value, according to the wiphy's
 *	signal type
 * @boottime_ns: timestamp (CLOCK_BOOTTIME) when the information was
 *	received; should match the time when the frame was actually
 *	received by the device (not just by the host, in case it was
 *	buffered on the device) and be accurate to about 10ms.
 *	If the frame isn't buffered, just passing the return value of
 *	ktime_get_boot_ns() is likely appropriate.
 */
struct cfg80211_inform_bss {
	struct ieee80211_channel *chan;
	enum nl80211_bss_scan_width scan_width;
	s32 signal;
	u64 boottime_ns;
};

/**
/**
 * struct cfg80211_bss_ie_data - BSS entry IE data
 * struct cfg80211_bss_ie_data - BSS entry IE data
 * @tsf: TSF contained in the frame that carried these IEs
 * @tsf: TSF contained in the frame that carried these IEs
@@ -3958,14 +3978,11 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy);
void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy);


/**
/**
 * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame
 * cfg80211_inform_bss_frame_data - inform cfg80211 of a received BSS frame
 *
 * @wiphy: the wiphy reporting the BSS
 * @wiphy: the wiphy reporting the BSS
 * @rx_channel: The channel the frame was received on
 * @data: the BSS metadata
 * @scan_width: width of the control channel
 * @mgmt: the management frame (probe response or beacon)
 * @mgmt: the management frame (probe response or beacon)
 * @len: length of the management frame
 * @len: length of the management frame
 * @signal: the signal strength, type depends on the wiphy's signal_type
 * @gfp: context flags
 * @gfp: context flags
 *
 *
 * This informs cfg80211 that BSS information was found and
 * This informs cfg80211 that BSS information was found and
@@ -3975,11 +3992,26 @@ void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy);
 * Or %NULL on error.
 * Or %NULL on error.
 */
 */
struct cfg80211_bss * __must_check
struct cfg80211_bss * __must_check
cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
			       struct cfg80211_inform_bss *data,
			       struct ieee80211_mgmt *mgmt, size_t len,
			       gfp_t gfp);

static inline struct cfg80211_bss * __must_check
cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
				struct ieee80211_channel *rx_channel,
				struct ieee80211_channel *rx_channel,
				enum nl80211_bss_scan_width scan_width,
				enum nl80211_bss_scan_width scan_width,
				struct ieee80211_mgmt *mgmt, size_t len,
				struct ieee80211_mgmt *mgmt, size_t len,
				s32 signal, gfp_t gfp);
				s32 signal, gfp_t gfp)
{
	struct cfg80211_inform_bss data = {
		.chan = rx_channel,
		.scan_width = scan_width,
		.signal = signal,
	};

	return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp);
}


static inline struct cfg80211_bss * __must_check
static inline struct cfg80211_bss * __must_check
cfg80211_inform_bss_frame(struct wiphy *wiphy,
cfg80211_inform_bss_frame(struct wiphy *wiphy,
@@ -3987,9 +4019,13 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
			  struct ieee80211_mgmt *mgmt, size_t len,
			  struct ieee80211_mgmt *mgmt, size_t len,
			  s32 signal, gfp_t gfp)
			  s32 signal, gfp_t gfp)
{
{
	return cfg80211_inform_bss_width_frame(wiphy, rx_channel,
	struct cfg80211_inform_bss data = {
					       NL80211_BSS_CHAN_WIDTH_20,
		.chan = rx_channel,
					       mgmt, len, signal, gfp);
		.scan_width = NL80211_BSS_CHAN_WIDTH_20,
		.signal = signal,
	};

	return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp);
}
}


/**
/**
@@ -4006,11 +4042,10 @@ enum cfg80211_bss_frame_type {
};
};


/**
/**
 * cfg80211_inform_bss_width - inform cfg80211 of a new BSS
 * cfg80211_inform_bss_data - inform cfg80211 of a new BSS
 *
 *
 * @wiphy: the wiphy reporting the BSS
 * @wiphy: the wiphy reporting the BSS
 * @rx_channel: The channel the frame was received on
 * @data: the BSS metadata
 * @scan_width: width of the control channel
 * @ftype: frame type (if known)
 * @ftype: frame type (if known)
 * @bssid: the BSSID of the BSS
 * @bssid: the BSSID of the BSS
 * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
 * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
@@ -4018,7 +4053,6 @@ enum cfg80211_bss_frame_type {
 * @beacon_interval: the beacon interval announced by the peer
 * @beacon_interval: the beacon interval announced by the peer
 * @ie: additional IEs sent by the peer
 * @ie: additional IEs sent by the peer
 * @ielen: length of the additional IEs
 * @ielen: length of the additional IEs
 * @signal: the signal strength, type depends on the wiphy's signal_type
 * @gfp: context flags
 * @gfp: context flags
 *
 *
 * This informs cfg80211 that BSS information was found and
 * This informs cfg80211 that BSS information was found and
@@ -4028,13 +4062,32 @@ enum cfg80211_bss_frame_type {
 * Or %NULL on error.
 * Or %NULL on error.
 */
 */
struct cfg80211_bss * __must_check
struct cfg80211_bss * __must_check
cfg80211_inform_bss_data(struct wiphy *wiphy,
			 struct cfg80211_inform_bss *data,
			 enum cfg80211_bss_frame_type ftype,
			 const u8 *bssid, u64 tsf, u16 capability,
			 u16 beacon_interval, const u8 *ie, size_t ielen,
			 gfp_t gfp);

static inline struct cfg80211_bss * __must_check
cfg80211_inform_bss_width(struct wiphy *wiphy,
cfg80211_inform_bss_width(struct wiphy *wiphy,
			  struct ieee80211_channel *rx_channel,
			  struct ieee80211_channel *rx_channel,
			  enum nl80211_bss_scan_width scan_width,
			  enum nl80211_bss_scan_width scan_width,
			  enum cfg80211_bss_frame_type ftype,
			  enum cfg80211_bss_frame_type ftype,
			  const u8 *bssid, u64 tsf, u16 capability,
			  const u8 *bssid, u64 tsf, u16 capability,
			  u16 beacon_interval, const u8 *ie, size_t ielen,
			  u16 beacon_interval, const u8 *ie, size_t ielen,
			  s32 signal, gfp_t gfp);
			  s32 signal, gfp_t gfp)
{
	struct cfg80211_inform_bss data = {
		.chan = rx_channel,
		.scan_width = scan_width,
		.signal = signal,
	};

	return cfg80211_inform_bss_data(wiphy, &data, ftype, bssid, tsf,
					capability, beacon_interval, ie, ielen,
					gfp);
}


static inline struct cfg80211_bss * __must_check
static inline struct cfg80211_bss * __must_check
cfg80211_inform_bss(struct wiphy *wiphy,
cfg80211_inform_bss(struct wiphy *wiphy,
@@ -4044,10 +4097,14 @@ cfg80211_inform_bss(struct wiphy *wiphy,
		    u16 beacon_interval, const u8 *ie, size_t ielen,
		    u16 beacon_interval, const u8 *ie, size_t ielen,
		    s32 signal, gfp_t gfp)
		    s32 signal, gfp_t gfp)
{
{
	return cfg80211_inform_bss_width(wiphy, rx_channel,
	struct cfg80211_inform_bss data = {
					 NL80211_BSS_CHAN_WIDTH_20, ftype,
		.chan = rx_channel,
					 bssid, tsf, capability,
		.scan_width = NL80211_BSS_CHAN_WIDTH_20,
					 beacon_interval, ie, ielen, signal,
		.signal = signal,
	};

	return cfg80211_inform_bss_data(wiphy, &data, ftype, bssid, tsf,
					capability, beacon_interval, ie, ielen,
					gfp);
					gfp);
}
}


+4 −0
Original line number Original line Diff line number Diff line
@@ -3364,6 +3364,9 @@ enum nl80211_bss_scan_width {
 *	(not present if no beacon frame has been received yet)
 *	(not present if no beacon frame has been received yet)
 * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
 * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
 *	@NL80211_BSS_TSF is known to be from a probe response (flag attribute)
 *	@NL80211_BSS_TSF is known to be from a probe response (flag attribute)
 * @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry
 *	was last updated by a received frame. The value is expected to be
 *	accurate to about 10ms. (u64, nanoseconds)
 * @__NL80211_BSS_AFTER_LAST: internal
 * @__NL80211_BSS_AFTER_LAST: internal
 * @NL80211_BSS_MAX: highest BSS attribute
 * @NL80211_BSS_MAX: highest BSS attribute
 */
 */
@@ -3383,6 +3386,7 @@ enum nl80211_bss {
	NL80211_BSS_CHAN_WIDTH,
	NL80211_BSS_CHAN_WIDTH,
	NL80211_BSS_BEACON_TSF,
	NL80211_BSS_BEACON_TSF,
	NL80211_BSS_PRESP_DATA,
	NL80211_BSS_PRESP_DATA,
	NL80211_BSS_LAST_SEEN_BOOTTIME,


	/* keep last */
	/* keep last */
	__NL80211_BSS_AFTER_LAST,
	__NL80211_BSS_AFTER_LAST,
+1 −0
Original line number Original line Diff line number Diff line
@@ -137,6 +137,7 @@ struct cfg80211_internal_bss {
	struct list_head list;
	struct list_head list;
	struct list_head hidden_list;
	struct list_head hidden_list;
	struct rb_node rbn;
	struct rb_node rbn;
	u64 ts_boottime;
	unsigned long ts;
	unsigned long ts;
	unsigned long refcount;
	unsigned long refcount;
	atomic_t hold;
	atomic_t hold;
+5 −0
Original line number Original line Diff line number Diff line
@@ -6605,6 +6605,11 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
			jiffies_to_msecs(jiffies - intbss->ts)))
			jiffies_to_msecs(jiffies - intbss->ts)))
		goto nla_put_failure;
		goto nla_put_failure;


	if (intbss->ts_boottime &&
	    nla_put_u64(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
			intbss->ts_boottime))
		goto nla_put_failure;

	switch (rdev->wiphy.signal_type) {
	switch (rdev->wiphy.signal_type) {
	case CFG80211_SIGNAL_TYPE_MBM:
	case CFG80211_SIGNAL_TYPE_MBM:
		if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
		if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
Loading