mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	mac802154: Handle active scanning
Active scan support is based on the current passive scan support, cheered up with beacon requests sent after every channel change. Co-developed-by: David Girault <david.girault@qorvo.com> Signed-off-by: David Girault <david.girault@qorvo.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Acked-by: Alexander Aring <aahringo@redhat.com> Link: https://lore.kernel.org/r/20230310145346.1397068-3-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
This commit is contained in:
		
							parent
							
								
									b886642641
								
							
						
					
					
						commit
						e2c3e6f53a
					
				
					 4 changed files with 92 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -74,6 +74,10 @@ struct ieee802154_beacon_hdr {
 | 
			
		|||
#endif
 | 
			
		||||
} __packed;
 | 
			
		||||
 | 
			
		||||
struct ieee802154_mac_cmd_pl {
 | 
			
		||||
	u8  cmd_id;
 | 
			
		||||
} __packed;
 | 
			
		||||
 | 
			
		||||
struct ieee802154_sechdr {
 | 
			
		||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
 | 
			
		||||
	u8 level:3,
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +153,16 @@ struct ieee802154_beacon_frame {
 | 
			
		|||
	struct ieee802154_beacon_hdr mac_pl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ieee802154_mac_cmd_frame {
 | 
			
		||||
	struct ieee802154_hdr mhr;
 | 
			
		||||
	struct ieee802154_mac_cmd_pl mac_pl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ieee802154_beacon_req_frame {
 | 
			
		||||
	struct ieee802154_hdr mhr;
 | 
			
		||||
	struct ieee802154_mac_cmd_pl mac_pl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
 | 
			
		||||
 * the contents of hdr will be, and the actual value of those bits in
 | 
			
		||||
 * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
 | 
			
		||||
| 
						 | 
				
			
			@ -174,9 +188,11 @@ int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
 | 
			
		|||
 */
 | 
			
		||||
int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
 | 
			
		||||
 | 
			
		||||
/* pushes a beacon frame into an skb */
 | 
			
		||||
/* pushes/pulls various frame types into/from an skb */
 | 
			
		||||
int ieee802154_beacon_push(struct sk_buff *skb,
 | 
			
		||||
			   struct ieee802154_beacon_frame *beacon);
 | 
			
		||||
int ieee802154_mac_cmd_push(struct sk_buff *skb, void *frame,
 | 
			
		||||
			    const void *pl, unsigned int pl_len);
 | 
			
		||||
 | 
			
		||||
int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,6 +120,29 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
 | 
			
		||||
 | 
			
		||||
int ieee802154_mac_cmd_push(struct sk_buff *skb, void *f,
 | 
			
		||||
			    const void *pl, unsigned int pl_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ieee802154_mac_cmd_frame *frame = f;
 | 
			
		||||
	struct ieee802154_mac_cmd_pl *mac_pl = &frame->mac_pl;
 | 
			
		||||
	struct ieee802154_hdr *mhr = &frame->mhr;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	skb_reserve(skb, sizeof(*mhr));
 | 
			
		||||
	ret = ieee802154_hdr_push(skb, mhr);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	skb_reset_mac_header(skb);
 | 
			
		||||
	skb->mac_len = ret;
 | 
			
		||||
 | 
			
		||||
	skb_put_data(skb, mac_pl, sizeof(*mac_pl));
 | 
			
		||||
	skb_put_data(skb, pl, pl_len);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(ieee802154_mac_cmd_push);
 | 
			
		||||
 | 
			
		||||
int ieee802154_beacon_push(struct sk_buff *skb,
 | 
			
		||||
			   struct ieee802154_beacon_frame *beacon)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,7 @@ struct ieee802154_local {
 | 
			
		|||
	/* Scanning */
 | 
			
		||||
	u8 scan_page;
 | 
			
		||||
	u8 scan_channel;
 | 
			
		||||
	struct ieee802154_beacon_req_frame scan_beacon_req;
 | 
			
		||||
	struct cfg802154_scan_request __rcu *scan_req;
 | 
			
		||||
	struct delayed_work scan_work;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,8 +18,12 @@
 | 
			
		|||
 | 
			
		||||
#define IEEE802154_BEACON_MHR_SZ 13
 | 
			
		||||
#define IEEE802154_BEACON_PL_SZ 4
 | 
			
		||||
#define IEEE802154_MAC_CMD_MHR_SZ 23
 | 
			
		||||
#define IEEE802154_MAC_CMD_PL_SZ 1
 | 
			
		||||
#define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \
 | 
			
		||||
				  IEEE802154_BEACON_PL_SZ)
 | 
			
		||||
#define IEEE802154_MAC_CMD_SKB_SZ (IEEE802154_MAC_CMD_MHR_SZ + \
 | 
			
		||||
				   IEEE802154_MAC_CMD_PL_SZ)
 | 
			
		||||
 | 
			
		||||
/* mac802154_scan_cleanup_locked() must be called upon scan completion or abort.
 | 
			
		||||
 * - Completions are asynchronous, not locked by the rtnl and decided by the
 | 
			
		||||
| 
						 | 
				
			
			@ -131,6 +135,42 @@ static int mac802154_scan_find_next_chan(struct ieee802154_local *local,
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mac802154_scan_prepare_beacon_req(struct ieee802154_local *local)
 | 
			
		||||
{
 | 
			
		||||
	memset(&local->scan_beacon_req, 0, sizeof(local->scan_beacon_req));
 | 
			
		||||
	local->scan_beacon_req.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
 | 
			
		||||
	local->scan_beacon_req.mhr.fc.dest_addr_mode = IEEE802154_SHORT_ADDRESSING;
 | 
			
		||||
	local->scan_beacon_req.mhr.fc.version = IEEE802154_2003_STD;
 | 
			
		||||
	local->scan_beacon_req.mhr.fc.source_addr_mode = IEEE802154_NO_ADDRESSING;
 | 
			
		||||
	local->scan_beacon_req.mhr.dest.mode = IEEE802154_ADDR_SHORT;
 | 
			
		||||
	local->scan_beacon_req.mhr.dest.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
 | 
			
		||||
	local->scan_beacon_req.mhr.dest.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
 | 
			
		||||
	local->scan_beacon_req.mac_pl.cmd_id = IEEE802154_CMD_BEACON_REQ;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mac802154_transmit_beacon_req(struct ieee802154_local *local,
 | 
			
		||||
					 struct ieee802154_sub_if_data *sdata)
 | 
			
		||||
{
 | 
			
		||||
	struct sk_buff *skb;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ, GFP_KERNEL);
 | 
			
		||||
	if (!skb)
 | 
			
		||||
		return -ENOBUFS;
 | 
			
		||||
 | 
			
		||||
	skb->dev = sdata->dev;
 | 
			
		||||
 | 
			
		||||
	ret = ieee802154_mac_cmd_push(skb, &local->scan_beacon_req, NULL, 0);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		kfree_skb(skb);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ieee802154_mlme_tx(local, sdata, skb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mac802154_scan_worker(struct work_struct *work)
 | 
			
		||||
{
 | 
			
		||||
	struct ieee802154_local *local =
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +246,13 @@ void mac802154_scan_worker(struct work_struct *work)
 | 
			
		|||
		goto end_scan;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (scan_req->type == NL802154_SCAN_ACTIVE) {
 | 
			
		||||
		ret = mac802154_transmit_beacon_req(local, sdata);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			dev_err(&sdata->dev->dev,
 | 
			
		||||
				"Error when transmitting beacon request (%d)\n", ret);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ieee802154_configure_durations(wpan_phy, page, channel);
 | 
			
		||||
	scan_duration = mac802154_scan_get_channel_time(scan_req_duration,
 | 
			
		||||
							wpan_phy->symbol_duration);
 | 
			
		||||
| 
						 | 
				
			
			@ -231,8 +278,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
 | 
			
		|||
	if (mac802154_is_scanning(local))
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	/* TODO: support other scanning type */
 | 
			
		||||
	if (request->type != NL802154_SCAN_PASSIVE)
 | 
			
		||||
	if (request->type != NL802154_SCAN_PASSIVE &&
 | 
			
		||||
	    request->type != NL802154_SCAN_ACTIVE)
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	/* Store scanning parameters */
 | 
			
		||||
| 
						 | 
				
			
			@ -247,6 +294,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
 | 
			
		|||
	local->scan_page = request->page;
 | 
			
		||||
	local->scan_channel = -1;
 | 
			
		||||
	set_bit(IEEE802154_IS_SCANNING, &local->ongoing);
 | 
			
		||||
	if (request->type == NL802154_SCAN_ACTIVE)
 | 
			
		||||
		mac802154_scan_prepare_beacon_req(local);
 | 
			
		||||
 | 
			
		||||
	nl802154_scan_started(request->wpan_phy, request->wpan_dev);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue