Skip to content

Commit

Permalink
Merge tag 'ieee802154-for-net-next-2023-06-23' of gitolite.kernel.org…
Browse files Browse the repository at this point in the history
…:pub/scm/linux/kernel/git/wpan/wpan-next

Miquel Raynal says:

====================
Core WPAN changes:
 - Support for active scans
 - Support for answering BEACON_REQ
 - Specific MLME handling for limited devices

WPAN driver changes:
 - ca8210:
   - Flag the devices as limited
   - Remove stray gpiod_unexport() call

* tag 'ieee802154-for-net-next-2023-06-23' of gitolite.kernel.org:pub/scm/linux/kernel/git/wpan/wpan-next:
  ieee802154: ca8210: Remove stray gpiod_unexport() call
  ieee802154: ca8210: Flag the driver as being limited
  net: ieee802154: Handle limited devices with only datagram support
  mac802154: Handle received BEACON_REQ
  ieee802154: Add support for allowing to answer BEACON_REQ
  mac802154: Handle active scanning
  ieee802154: Add support for user active scan requests
====================

Link: https://lore.kernel.org/r/20230623195506.40b87b5f@xps-13
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed Jun 24, 2023
2 parents 14fd5e0 + 18b849f commit 2ffecf1
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 11 deletions.
4 changes: 2 additions & 2 deletions drivers/net/ieee802154/ca8210.c
Original file line number Diff line number Diff line change
Expand Up @@ -2855,7 +2855,6 @@ static int ca8210_interrupt_init(struct spi_device *spi)
);
if (ret) {
dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id);
gpiod_unexport(gpio_to_desc(pdata->gpio_irq));
gpio_free(pdata->gpio_irq);
}

Expand Down Expand Up @@ -2945,7 +2944,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
ca8210_hw->phy->flags =
WPAN_PHY_FLAG_TXPOWER |
WPAN_PHY_FLAG_CCA_ED_LEVEL |
WPAN_PHY_FLAG_CCA_MODE;
WPAN_PHY_FLAG_CCA_MODE |
WPAN_PHY_FLAG_DATAGRAMS_ONLY;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions include/net/cfg802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,15 @@ wpan_phy_cca_cmp(const struct wpan_phy_cca *a, const struct wpan_phy_cca *b)
* setting.
* @WPAN_PHY_FLAG_STATE_QUEUE_STOPPED: Indicates that the transmit queue was
* temporarily stopped.
* @WPAN_PHY_FLAG_DATAGRAMS_ONLY: Indicates that transceiver is only able to
* send/receive datagrams.
*/
enum wpan_phy_flags {
WPAN_PHY_FLAG_TXPOWER = BIT(1),
WPAN_PHY_FLAG_CCA_ED_LEVEL = BIT(2),
WPAN_PHY_FLAG_CCA_MODE = BIT(3),
WPAN_PHY_FLAG_STATE_QUEUE_STOPPED = BIT(4),
WPAN_PHY_FLAG_DATAGRAMS_ONLY = BIT(5),
};

struct wpan_phy {
Expand Down
20 changes: 19 additions & 1 deletion include/net/ieee802154_netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -174,9 +188,13 @@ 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_mac_cmd_pl_pull(struct sk_buff *skb,
struct ieee802154_mac_cmd_pl *mac_pl);

int ieee802154_max_payload(const struct ieee802154_hdr *hdr);

Expand Down
36 changes: 36 additions & 0 deletions net/ieee802154/header_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -284,6 +307,19 @@ ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr)
}
EXPORT_SYMBOL_GPL(ieee802154_hdr_pull);

int ieee802154_mac_cmd_pl_pull(struct sk_buff *skb,
struct ieee802154_mac_cmd_pl *mac_pl)
{
if (!pskb_may_pull(skb, sizeof(*mac_pl)))
return -EINVAL;

memcpy(mac_pl, skb->data, sizeof(*mac_pl));
skb_pull(skb, sizeof(*mac_pl));

return 0;
}
EXPORT_SYMBOL_GPL(ieee802154_mac_cmd_pl_pull);

int
ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr)
{
Expand Down
13 changes: 12 additions & 1 deletion net/ieee802154/nl802154.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
NLA_POLICY_RANGE(NLA_U8, NL802154_SCAN_DONE_REASON_FINISHED,
NL802154_SCAN_DONE_REASON_ABORTED),
[NL802154_ATTR_BEACON_INTERVAL] =
NLA_POLICY_MAX(NLA_U8, IEEE802154_MAX_SCAN_DURATION),
NLA_POLICY_MAX(NLA_U8, IEEE802154_ACTIVE_SCAN_DURATION),

#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
Expand Down Expand Up @@ -1417,6 +1417,11 @@ static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}

if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
return -EOPNOTSUPP;
}

request = kzalloc(sizeof(*request), GFP_KERNEL);
if (!request)
return -ENOMEM;
Expand All @@ -1426,6 +1431,7 @@ static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)

type = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE]);
switch (type) {
case NL802154_SCAN_ACTIVE:
case NL802154_SCAN_PASSIVE:
request->type = type;
break;
Expand Down Expand Up @@ -1583,6 +1589,11 @@ nl802154_send_beacons(struct sk_buff *skb, struct genl_info *info)
return -EPERM;
}

if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
return -EOPNOTSUPP;
}

request = kzalloc(sizeof(*request), GFP_KERNEL);
if (!request)
return -ENOMEM;
Expand Down
21 changes: 21 additions & 0 deletions net/mac802154/ieee802154_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -70,6 +71,8 @@ struct ieee802154_local {
/* Asynchronous tasks */
struct list_head rx_beacon_list;
struct work_struct rx_beacon_work;
struct list_head rx_mac_cmd_list;
struct work_struct rx_mac_cmd_work;

bool started;
bool suspended;
Expand Down Expand Up @@ -154,6 +157,22 @@ ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata)
return test_bit(SDATA_STATE_RUNNING, &sdata->state);
}

static inline int ieee802154_get_mac_cmd(struct sk_buff *skb, u8 *mac_cmd)
{
struct ieee802154_mac_cmd_pl mac_pl;
int ret;

if (mac_cb(skb)->type != IEEE802154_FC_TYPE_MAC_CMD)
return -EINVAL;

ret = ieee802154_mac_cmd_pl_pull(skb, &mac_pl);
if (ret)
return ret;

*mac_cmd = mac_pl.cmd_id;
return 0;
}

extern struct ieee802154_mlme_ops mac802154_mlme_wpan;

void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
Expand Down Expand Up @@ -275,6 +294,8 @@ static inline bool mac802154_is_beaconing(struct ieee802154_local *local)
return test_bit(IEEE802154_IS_BEACONING, &local->ongoing);
}

void mac802154_rx_mac_cmd_worker(struct work_struct *work);

/* interface handling */
int ieee802154_iface_init(void);
void ieee802154_iface_exit(void);
Expand Down
2 changes: 2 additions & 0 deletions net/mac802154/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)

INIT_LIST_HEAD(&local->interfaces);
INIT_LIST_HEAD(&local->rx_beacon_list);
INIT_LIST_HEAD(&local->rx_mac_cmd_list);
mutex_init(&local->iflist_mtx);

tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
Expand All @@ -100,6 +101,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_worker);
INIT_WORK(&local->rx_beacon_work, mac802154_rx_beacon_worker);
INIT_DELAYED_WORK(&local->beacon_work, mac802154_beacon_worker);
INIT_WORK(&local->rx_mac_cmd_work, mac802154_rx_mac_cmd_worker);

/* init supported flags with 802.15.4 default ranges */
phy->supported.max_minbe = 8;
Expand Down
70 changes: 69 additions & 1 deletion net/mac802154/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,62 @@ void mac802154_rx_beacon_worker(struct work_struct *work)
kfree(mac_pkt);
}

static bool mac802154_should_answer_beacon_req(struct ieee802154_local *local)
{
struct cfg802154_beacon_request *beacon_req;
unsigned int interval;

rcu_read_lock();
beacon_req = rcu_dereference(local->beacon_req);
if (!beacon_req) {
rcu_read_unlock();
return false;
}

interval = beacon_req->interval;
rcu_read_unlock();

if (!mac802154_is_beaconing(local))
return false;

return interval == IEEE802154_ACTIVE_SCAN_DURATION;
}

void mac802154_rx_mac_cmd_worker(struct work_struct *work)
{
struct ieee802154_local *local =
container_of(work, struct ieee802154_local, rx_mac_cmd_work);
struct cfg802154_mac_pkt *mac_pkt;
u8 mac_cmd;
int rc;

mac_pkt = list_first_entry_or_null(&local->rx_mac_cmd_list,
struct cfg802154_mac_pkt, node);
if (!mac_pkt)
return;

rc = ieee802154_get_mac_cmd(mac_pkt->skb, &mac_cmd);
if (rc)
goto out;

switch (mac_cmd) {
case IEEE802154_CMD_BEACON_REQ:
dev_dbg(&mac_pkt->sdata->dev->dev, "processing BEACON REQ\n");
if (!mac802154_should_answer_beacon_req(local))
break;

queue_delayed_work(local->mac_wq, &local->beacon_work, 0);
break;
default:
break;
}

out:
list_del(&mac_pkt->node);
kfree_skb(mac_pkt->skb);
kfree(mac_pkt);
}

static int
ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
struct sk_buff *skb, const struct ieee802154_hdr *hdr)
Expand Down Expand Up @@ -140,8 +196,20 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
list_add_tail(&mac_pkt->node, &sdata->local->rx_beacon_list);
queue_work(sdata->local->mac_wq, &sdata->local->rx_beacon_work);
return NET_RX_SUCCESS;
case IEEE802154_FC_TYPE_ACK:

case IEEE802154_FC_TYPE_MAC_CMD:
dev_dbg(&sdata->dev->dev, "MAC COMMAND received\n");
mac_pkt = kzalloc(sizeof(*mac_pkt), GFP_ATOMIC);
if (!mac_pkt)
goto fail;

mac_pkt->skb = skb_get(skb);
mac_pkt->sdata = sdata;
list_add_tail(&mac_pkt->node, &sdata->local->rx_mac_cmd_list);
queue_work(sdata->local->mac_wq, &sdata->local->rx_mac_cmd_work);
return NET_RX_SUCCESS;

case IEEE802154_FC_TYPE_ACK:
goto fail;

case IEEE802154_FC_TYPE_DATA:
Expand Down
Loading

0 comments on commit 2ffecf1

Please sign in to comment.