Commit 3accf476 authored by Miquel Raynal's avatar Miquel Raynal Committed by Stefan Schmidt
Browse files

mac802154: Handle basic beaconing



Implement the core hooks in order to provide the softMAC layer support
for sending beacons. Coordinators may be requested to send beacons in a
beacon enabled PAN in order for the other devices around to self
discover the available PANs automatically.

Changing the channels is prohibited while a beacon operation is
ongoing.

The implementation uses a workqueue triggered at a certain interval
depending on the symbol duration for the current channel and the
interval order provided.

Sending beacons in response to a BEACON_REQ frame (ie. answering active
scans) is not yet supported.

This initial patchset has no security support (llsec).

Co-developed-by: default avatarDavid Girault <david.girault@qorvo.com>
Signed-off-by: default avatarDavid Girault <david.girault@qorvo.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Acked-by: default avatarAlexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/r/20230125102923.135465-3-miquel.raynal@bootlin.com


Signed-off-by: default avatarStefan Schmidt <stefan@datenfreihafen.org>
parent 9bc11450
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -129,6 +129,13 @@ enum ieee802154_frame_version {
	IEEE802154_MULTIPURPOSE_STD = IEEE802154_2003_STD,
};

enum ieee802154_addressing_mode {
	IEEE802154_NO_ADDRESSING,
	IEEE802154_RESERVED,
	IEEE802154_SHORT_ADDRESSING,
	IEEE802154_EXTENDED_ADDRESSING,
};

struct ieee802154_hdr {
	struct ieee802154_hdr_fc fc;
	u8 seq;
@@ -137,6 +144,11 @@ struct ieee802154_hdr {
	struct ieee802154_sechdr sec;
};

struct ieee802154_beacon_frame {
	struct ieee802154_hdr mhr;
	struct ieee802154_beacon_hdr 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
@@ -162,6 +174,10 @@ 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 */
int ieee802154_beacon_push(struct sk_buff *skb,
			   struct ieee802154_beacon_frame *beacon);

int ieee802154_max_payload(const struct ieee802154_hdr *hdr);

static inline int
+24 −0
Original line number Diff line number Diff line
@@ -120,6 +120,30 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
}
EXPORT_SYMBOL_GPL(ieee802154_hdr_push);

int ieee802154_beacon_push(struct sk_buff *skb,
			   struct ieee802154_beacon_frame *beacon)
{
	struct ieee802154_beacon_hdr *mac_pl = &beacon->mac_pl;
	struct ieee802154_hdr *mhr = &beacon->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));

	if (mac_pl->pend_short_addr_count || mac_pl->pend_ext_addr_count)
		return -EOPNOTSUPP;

	return 0;
}
EXPORT_SYMBOL_GPL(ieee802154_beacon_push);

static int
ieee802154_hdr_get_addr(const u8 *buf, int mode, bool omit_pan,
			struct ieee802154_addr *addr)
+29 −2
Original line number Diff line number Diff line
@@ -114,8 +114,8 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
	    wpan_phy->current_channel == channel)
		return 0;

	/* Refuse to change channels during a scanning operation */
	if (mac802154_is_scanning(local))
	/* Refuse to change channels during scanning or beaconing */
	if (mac802154_is_scanning(local) || mac802154_is_beaconing(local))
		return -EBUSY;

	ret = drv_set_channel(local, page, channel);
@@ -290,6 +290,31 @@ static int mac802154_abort_scan(struct wpan_phy *wpan_phy,
	return mac802154_abort_scan_locked(local, sdata);
}

static int mac802154_send_beacons(struct wpan_phy *wpan_phy,
				  struct cfg802154_beacon_request *request)
{
	struct ieee802154_sub_if_data *sdata;

	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(request->wpan_dev);

	ASSERT_RTNL();

	return mac802154_send_beacons_locked(sdata, request);
}

static int mac802154_stop_beacons(struct wpan_phy *wpan_phy,
				  struct wpan_dev *wpan_dev)
{
	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
	struct ieee802154_sub_if_data *sdata;

	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev);

	ASSERT_RTNL();

	return mac802154_stop_beacons_locked(local, sdata);
}

#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
static void
ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -499,6 +524,8 @@ const struct cfg802154_ops mac802154_config_ops = {
	.set_ackreq_default = ieee802154_set_ackreq_default,
	.trigger_scan = mac802154_trigger_scan,
	.abort_scan = mac802154_abort_scan,
	.send_beacons = mac802154_send_beacons,
	.stop_beacons = mac802154_stop_beacons,
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
	.get_llsec_table = ieee802154_get_llsec_table,
	.lock_llsec_table = ieee802154_lock_llsec_table,
+18 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

enum ieee802154_ongoing {
	IEEE802154_IS_SCANNING = BIT(0),
	IEEE802154_IS_BEACONING = BIT(1),
};

/* mac802154 device private data */
@@ -60,6 +61,12 @@ struct ieee802154_local {
	struct cfg802154_scan_request __rcu *scan_req;
	struct delayed_work scan_work;

	/* Beaconing */
	unsigned int beacon_interval;
	struct ieee802154_beacon_frame beacon;
	struct cfg802154_beacon_request __rcu *beacon_req;
	struct delayed_work beacon_work;

	/* Asynchronous tasks */
	struct list_head rx_beacon_list;
	struct work_struct rx_beacon_work;
@@ -257,6 +264,17 @@ static inline bool mac802154_is_scanning(struct ieee802154_local *local)
	return test_bit(IEEE802154_IS_SCANNING, &local->ongoing);
}

void mac802154_beacon_worker(struct work_struct *work);
int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
				  struct cfg802154_beacon_request *request);
int mac802154_stop_beacons_locked(struct ieee802154_local *local,
				  struct ieee802154_sub_if_data *sdata);

static inline bool mac802154_is_beaconing(struct ieee802154_local *local)
{
	return test_bit(IEEE802154_IS_BEACONING, &local->ongoing);
}

/* interface handling */
int ieee802154_iface_init(void);
void ieee802154_iface_exit(void);
+3 −0
Original line number Diff line number Diff line
@@ -305,6 +305,9 @@ static int mac802154_slave_close(struct net_device *dev)
	if (mac802154_is_scanning(local))
		mac802154_abort_scan_locked(local, sdata);

	if (mac802154_is_beaconing(local))
		mac802154_stop_beacons_locked(local, sdata);

	netif_stop_queue(dev);
	local->open_count--;

Loading