Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Miquel Raynal and committed by
Stefan Schmidt
e2c3e6f5 b8866426

+92 -3
+17 -1
include/net/ieee802154_netdev.h
··· 74 74 #endif 75 75 } __packed; 76 76 77 + struct ieee802154_mac_cmd_pl { 78 + u8 cmd_id; 79 + } __packed; 80 + 77 81 struct ieee802154_sechdr { 78 82 #if defined(__LITTLE_ENDIAN_BITFIELD) 79 83 u8 level:3, ··· 153 149 struct ieee802154_beacon_hdr mac_pl; 154 150 }; 155 151 152 + struct ieee802154_mac_cmd_frame { 153 + struct ieee802154_hdr mhr; 154 + struct ieee802154_mac_cmd_pl mac_pl; 155 + }; 156 + 157 + struct ieee802154_beacon_req_frame { 158 + struct ieee802154_hdr mhr; 159 + struct ieee802154_mac_cmd_pl mac_pl; 160 + }; 161 + 156 162 /* pushes hdr onto the skb. fields of hdr->fc that can be calculated from 157 163 * the contents of hdr will be, and the actual value of those bits in 158 164 * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame ··· 188 174 */ 189 175 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr); 190 176 191 - /* pushes a beacon frame into an skb */ 177 + /* pushes/pulls various frame types into/from an skb */ 192 178 int ieee802154_beacon_push(struct sk_buff *skb, 193 179 struct ieee802154_beacon_frame *beacon); 180 + int ieee802154_mac_cmd_push(struct sk_buff *skb, void *frame, 181 + const void *pl, unsigned int pl_len); 194 182 195 183 int ieee802154_max_payload(const struct ieee802154_hdr *hdr); 196 184
+23
net/ieee802154/header_ops.c
··· 120 120 } 121 121 EXPORT_SYMBOL_GPL(ieee802154_hdr_push); 122 122 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 + 123 146 int ieee802154_beacon_push(struct sk_buff *skb, 124 147 struct ieee802154_beacon_frame *beacon) 125 148 {
+1
net/mac802154/ieee802154_i.h
··· 58 58 /* Scanning */ 59 59 u8 scan_page; 60 60 u8 scan_channel; 61 + struct ieee802154_beacon_req_frame scan_beacon_req; 61 62 struct cfg802154_scan_request __rcu *scan_req; 62 63 struct delayed_work scan_work; 63 64
+51 -2
net/mac802154/scan.c
··· 18 18 19 19 #define IEEE802154_BEACON_MHR_SZ 13 20 20 #define IEEE802154_BEACON_PL_SZ 4 21 + #define IEEE802154_MAC_CMD_MHR_SZ 23 22 + #define IEEE802154_MAC_CMD_PL_SZ 1 21 23 #define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \ 22 24 IEEE802154_BEACON_PL_SZ) 25 + #define IEEE802154_MAC_CMD_SKB_SZ (IEEE802154_MAC_CMD_MHR_SZ + \ 26 + IEEE802154_MAC_CMD_PL_SZ) 23 27 24 28 /* mac802154_scan_cleanup_locked() must be called upon scan completion or abort. 25 29 * - Completions are asynchronous, not locked by the rtnl and decided by the ··· 135 131 return 0; 136 132 } 137 133 134 + static int mac802154_scan_prepare_beacon_req(struct ieee802154_local *local) 135 + { 136 + memset(&local->scan_beacon_req, 0, sizeof(local->scan_beacon_req)); 137 + local->scan_beacon_req.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD; 138 + local->scan_beacon_req.mhr.fc.dest_addr_mode = IEEE802154_SHORT_ADDRESSING; 139 + local->scan_beacon_req.mhr.fc.version = IEEE802154_2003_STD; 140 + local->scan_beacon_req.mhr.fc.source_addr_mode = IEEE802154_NO_ADDRESSING; 141 + local->scan_beacon_req.mhr.dest.mode = IEEE802154_ADDR_SHORT; 142 + local->scan_beacon_req.mhr.dest.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); 143 + local->scan_beacon_req.mhr.dest.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); 144 + local->scan_beacon_req.mac_pl.cmd_id = IEEE802154_CMD_BEACON_REQ; 145 + 146 + return 0; 147 + } 148 + 149 + static int mac802154_transmit_beacon_req(struct ieee802154_local *local, 150 + struct ieee802154_sub_if_data *sdata) 151 + { 152 + struct sk_buff *skb; 153 + int ret; 154 + 155 + skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ, GFP_KERNEL); 156 + if (!skb) 157 + return -ENOBUFS; 158 + 159 + skb->dev = sdata->dev; 160 + 161 + ret = ieee802154_mac_cmd_push(skb, &local->scan_beacon_req, NULL, 0); 162 + if (ret) { 163 + kfree_skb(skb); 164 + return ret; 165 + } 166 + 167 + return ieee802154_mlme_tx(local, sdata, skb); 168 + } 169 + 138 170 void mac802154_scan_worker(struct work_struct *work) 139 171 { 140 172 struct ieee802154_local *local = ··· 246 206 goto end_scan; 247 207 } 248 208 209 + if (scan_req->type == NL802154_SCAN_ACTIVE) { 210 + ret = mac802154_transmit_beacon_req(local, sdata); 211 + if (ret) 212 + dev_err(&sdata->dev->dev, 213 + "Error when transmitting beacon request (%d)\n", ret); 214 + } 215 + 249 216 ieee802154_configure_durations(wpan_phy, page, channel); 250 217 scan_duration = mac802154_scan_get_channel_time(scan_req_duration, 251 218 wpan_phy->symbol_duration); ··· 278 231 if (mac802154_is_scanning(local)) 279 232 return -EBUSY; 280 233 281 - /* TODO: support other scanning type */ 282 - if (request->type != NL802154_SCAN_PASSIVE) 234 + if (request->type != NL802154_SCAN_PASSIVE && 235 + request->type != NL802154_SCAN_ACTIVE) 283 236 return -EOPNOTSUPP; 284 237 285 238 /* Store scanning parameters */ ··· 294 247 local->scan_page = request->page; 295 248 local->scan_channel = -1; 296 249 set_bit(IEEE802154_IS_SCANNING, &local->ongoing); 250 + if (request->type == NL802154_SCAN_ACTIVE) 251 + mac802154_scan_prepare_beacon_req(local); 297 252 298 253 nl802154_scan_started(request->wpan_phy, request->wpan_dev); 299 254