Skip to content

Commit e2c3e6f

Browse files
miquelraynalStefan-Schmidt
authored andcommitted
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>
1 parent b886642 commit e2c3e6f

4 files changed

Lines changed: 92 additions & 3 deletions

File tree

include/net/ieee802154_netdev.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ struct ieee802154_beacon_hdr {
7474
#endif
7575
} __packed;
7676

77+
struct ieee802154_mac_cmd_pl {
78+
u8 cmd_id;
79+
} __packed;
80+
7781
struct ieee802154_sechdr {
7882
#if defined(__LITTLE_ENDIAN_BITFIELD)
7983
u8 level:3,
@@ -149,6 +153,16 @@ struct ieee802154_beacon_frame {
149153
struct ieee802154_beacon_hdr mac_pl;
150154
};
151155

156+
struct ieee802154_mac_cmd_frame {
157+
struct ieee802154_hdr mhr;
158+
struct ieee802154_mac_cmd_pl mac_pl;
159+
};
160+
161+
struct ieee802154_beacon_req_frame {
162+
struct ieee802154_hdr mhr;
163+
struct ieee802154_mac_cmd_pl mac_pl;
164+
};
165+
152166
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
153167
* the contents of hdr will be, and the actual value of those bits in
154168
* 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,
174188
*/
175189
int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
176190

177-
/* pushes a beacon frame into an skb */
191+
/* pushes/pulls various frame types into/from an skb */
178192
int ieee802154_beacon_push(struct sk_buff *skb,
179193
struct ieee802154_beacon_frame *beacon);
194+
int ieee802154_mac_cmd_push(struct sk_buff *skb, void *frame,
195+
const void *pl, unsigned int pl_len);
180196

181197
int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
182198

net/ieee802154/header_ops.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,29 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
120120
}
121121
EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
122122

123+
int ieee802154_mac_cmd_push(struct sk_buff *skb, void *f,
124+
const void *pl, unsigned int pl_len)
125+
{
126+
struct ieee802154_mac_cmd_frame *frame = f;
127+
struct ieee802154_mac_cmd_pl *mac_pl = &frame->mac_pl;
128+
struct ieee802154_hdr *mhr = &frame->mhr;
129+
int ret;
130+
131+
skb_reserve(skb, sizeof(*mhr));
132+
ret = ieee802154_hdr_push(skb, mhr);
133+
if (ret < 0)
134+
return ret;
135+
136+
skb_reset_mac_header(skb);
137+
skb->mac_len = ret;
138+
139+
skb_put_data(skb, mac_pl, sizeof(*mac_pl));
140+
skb_put_data(skb, pl, pl_len);
141+
142+
return 0;
143+
}
144+
EXPORT_SYMBOL_GPL(ieee802154_mac_cmd_push);
145+
123146
int ieee802154_beacon_push(struct sk_buff *skb,
124147
struct ieee802154_beacon_frame *beacon)
125148
{

net/mac802154/ieee802154_i.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct ieee802154_local {
5858
/* Scanning */
5959
u8 scan_page;
6060
u8 scan_channel;
61+
struct ieee802154_beacon_req_frame scan_beacon_req;
6162
struct cfg802154_scan_request __rcu *scan_req;
6263
struct delayed_work scan_work;
6364

net/mac802154/scan.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818

1919
#define IEEE802154_BEACON_MHR_SZ 13
2020
#define IEEE802154_BEACON_PL_SZ 4
21+
#define IEEE802154_MAC_CMD_MHR_SZ 23
22+
#define IEEE802154_MAC_CMD_PL_SZ 1
2123
#define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \
2224
IEEE802154_BEACON_PL_SZ)
25+
#define IEEE802154_MAC_CMD_SKB_SZ (IEEE802154_MAC_CMD_MHR_SZ + \
26+
IEEE802154_MAC_CMD_PL_SZ)
2327

2428
/* mac802154_scan_cleanup_locked() must be called upon scan completion or abort.
2529
* - 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,
131135
return 0;
132136
}
133137

138+
static int mac802154_scan_prepare_beacon_req(struct ieee802154_local *local)
139+
{
140+
memset(&local->scan_beacon_req, 0, sizeof(local->scan_beacon_req));
141+
local->scan_beacon_req.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
142+
local->scan_beacon_req.mhr.fc.dest_addr_mode = IEEE802154_SHORT_ADDRESSING;
143+
local->scan_beacon_req.mhr.fc.version = IEEE802154_2003_STD;
144+
local->scan_beacon_req.mhr.fc.source_addr_mode = IEEE802154_NO_ADDRESSING;
145+
local->scan_beacon_req.mhr.dest.mode = IEEE802154_ADDR_SHORT;
146+
local->scan_beacon_req.mhr.dest.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
147+
local->scan_beacon_req.mhr.dest.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
148+
local->scan_beacon_req.mac_pl.cmd_id = IEEE802154_CMD_BEACON_REQ;
149+
150+
return 0;
151+
}
152+
153+
static int mac802154_transmit_beacon_req(struct ieee802154_local *local,
154+
struct ieee802154_sub_if_data *sdata)
155+
{
156+
struct sk_buff *skb;
157+
int ret;
158+
159+
skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ, GFP_KERNEL);
160+
if (!skb)
161+
return -ENOBUFS;
162+
163+
skb->dev = sdata->dev;
164+
165+
ret = ieee802154_mac_cmd_push(skb, &local->scan_beacon_req, NULL, 0);
166+
if (ret) {
167+
kfree_skb(skb);
168+
return ret;
169+
}
170+
171+
return ieee802154_mlme_tx(local, sdata, skb);
172+
}
173+
134174
void mac802154_scan_worker(struct work_struct *work)
135175
{
136176
struct ieee802154_local *local =
@@ -206,6 +246,13 @@ void mac802154_scan_worker(struct work_struct *work)
206246
goto end_scan;
207247
}
208248

249+
if (scan_req->type == NL802154_SCAN_ACTIVE) {
250+
ret = mac802154_transmit_beacon_req(local, sdata);
251+
if (ret)
252+
dev_err(&sdata->dev->dev,
253+
"Error when transmitting beacon request (%d)\n", ret);
254+
}
255+
209256
ieee802154_configure_durations(wpan_phy, page, channel);
210257
scan_duration = mac802154_scan_get_channel_time(scan_req_duration,
211258
wpan_phy->symbol_duration);
@@ -231,8 +278,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
231278
if (mac802154_is_scanning(local))
232279
return -EBUSY;
233280

234-
/* TODO: support other scanning type */
235-
if (request->type != NL802154_SCAN_PASSIVE)
281+
if (request->type != NL802154_SCAN_PASSIVE &&
282+
request->type != NL802154_SCAN_ACTIVE)
236283
return -EOPNOTSUPP;
237284

238285
/* Store scanning parameters */
@@ -247,6 +294,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
247294
local->scan_page = request->page;
248295
local->scan_channel = -1;
249296
set_bit(IEEE802154_IS_SCANNING, &local->ongoing);
297+
if (request->type == NL802154_SCAN_ACTIVE)
298+
mac802154_scan_prepare_beacon_req(local);
250299

251300
nl802154_scan_started(request->wpan_phy, request->wpan_dev);
252301

0 commit comments

Comments
 (0)