net: l2: ieee802154: mgmt: allow beacon payload
The standard does allow for a optional beacon payload, which gets lost during scan, that could be interesting for the application to access in the NET_EVENT_IEEE802154_SCAN_RESULT callback. See section 7.3.1.6 in IEEE Std 802.15.4 for more information about the beacon payload field. And section 7.3.1 and figure 7-5 about general beacon frame format. Signed-off-by: Fabian Pflug <fabian.pflug@grandcentrix.net>
This commit is contained in:
parent
293fa118df
commit
ca53d2bf80
5 changed files with 42 additions and 10 deletions
|
@ -330,6 +330,11 @@ struct ieee802154_req_params {
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
/** Link quality information, between 0 and 255 */
|
/** Link quality information, between 0 and 255 */
|
||||||
uint8_t lqi;
|
uint8_t lqi;
|
||||||
|
|
||||||
|
/** Additional payload of the beacon if any.*/
|
||||||
|
uint8_t *beacon_payload;
|
||||||
|
/** Length of the additional payload. */
|
||||||
|
size_t beacon_payload_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -194,30 +194,32 @@ ieee802154_validate_aux_security_hdr(uint8_t *buf, uint8_t **p_buf, uint8_t *len
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
|
#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
|
||||||
|
|
||||||
static inline bool validate_beacon(struct ieee802154_mpdu *mpdu, uint8_t *buf, uint8_t length)
|
int ieee802514_beacon_header_length(uint8_t *buf, uint8_t length)
|
||||||
{
|
{
|
||||||
struct ieee802154_beacon *beacon = (struct ieee802154_beacon *)buf;
|
struct ieee802154_beacon *beacon = (struct ieee802154_beacon *)buf;
|
||||||
struct ieee802154_pas_spec *pas;
|
struct ieee802154_pas_spec *pas;
|
||||||
uint8_t len = IEEE802154_BEACON_SF_SIZE + IEEE802154_BEACON_GTS_SPEC_SIZE;
|
uint8_t len = IEEE802154_BEACON_SF_SIZE + IEEE802154_BEACON_GTS_SPEC_SIZE;
|
||||||
|
|
||||||
if (length < len) {
|
if (length < len) {
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* see section 7.3.1.5 on how to calculate GTS length */
|
||||||
if (beacon->gts.desc_count) {
|
if (beacon->gts.desc_count) {
|
||||||
len += IEEE802154_BEACON_GTS_DIR_SIZE +
|
len += IEEE802154_BEACON_GTS_DIR_SIZE +
|
||||||
beacon->gts.desc_count * IEEE802154_BEACON_GTS_SIZE;
|
beacon->gts.desc_count * IEEE802154_BEACON_GTS_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < len) {
|
if (length < len) {
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* see section 7.3.1.6 on how to calculate pending address length */
|
||||||
pas = (struct ieee802154_pas_spec *)buf + len;
|
pas = (struct ieee802154_pas_spec *)buf + len;
|
||||||
|
|
||||||
len += IEEE802154_BEACON_PAS_SPEC_SIZE;
|
len += IEEE802154_BEACON_PAS_SPEC_SIZE;
|
||||||
if (length < len) {
|
if (length < len) {
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pas->nb_sap || pas->nb_eap) {
|
if (pas->nb_sap || pas->nb_eap) {
|
||||||
|
@ -226,12 +228,10 @@ static inline bool validate_beacon(struct ieee802154_mpdu *mpdu, uint8_t *buf, u
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < len) {
|
if (length < len) {
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpdu->beacon = beacon;
|
return len;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool validate_mac_command_cfi_to_mhr(struct ieee802154_mhr *mhr,
|
static inline bool validate_mac_command_cfi_to_mhr(struct ieee802154_mhr *mhr,
|
||||||
|
@ -376,7 +376,7 @@ static inline bool validate_payload_and_mfr(struct ieee802154_mpdu *mpdu, uint8_
|
||||||
NET_DBG("Header size: %u, payload size %u", (uint32_t)(p_buf - buf), length);
|
NET_DBG("Header size: %u, payload size %u", (uint32_t)(p_buf - buf), length);
|
||||||
|
|
||||||
if (type == IEEE802154_FRAME_TYPE_BEACON) {
|
if (type == IEEE802154_FRAME_TYPE_BEACON) {
|
||||||
if (!validate_beacon(mpdu, p_buf, length)) {
|
if (ieee802514_beacon_header_length(p_buf, length) < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (type == IEEE802154_FRAME_TYPE_DATA) {
|
} else if (type == IEEE802154_FRAME_TYPE_DATA) {
|
||||||
|
|
|
@ -472,6 +472,20 @@ ieee802154_validate_aux_security_hdr(uint8_t *buf, uint8_t **p_buf, uint8_t *len
|
||||||
struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_buf,
|
struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_buf,
|
||||||
uint8_t *length);
|
uint8_t *length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the beacon header length.
|
||||||
|
*
|
||||||
|
* @details Returns the length of the MAC payload without the beacon payload,
|
||||||
|
* see section 7.3.1.1, figure 7-5.
|
||||||
|
*
|
||||||
|
* @param buf pointer to the MAC payload
|
||||||
|
* @param length buffer length
|
||||||
|
*
|
||||||
|
* @retval -EINVAL The header is invalid.
|
||||||
|
* @return the length of the beacon header
|
||||||
|
*/
|
||||||
|
int ieee802514_beacon_header_length(uint8_t *buf, uint8_t length);
|
||||||
|
|
||||||
bool ieee802154_validate_frame(uint8_t *buf, uint8_t length, struct ieee802154_mpdu *mpdu);
|
bool ieee802154_validate_frame(uint8_t *buf, uint8_t length, struct ieee802154_mpdu *mpdu);
|
||||||
|
|
||||||
void ieee802154_compute_header_and_authtag_len(struct net_if *iface, struct net_linkaddr *dst,
|
void ieee802154_compute_header_and_authtag_len(struct net_if *iface, struct net_linkaddr *dst,
|
||||||
|
|
|
@ -37,6 +37,7 @@ enum net_verdict ieee802154_handle_beacon(struct net_if *iface,
|
||||||
uint8_t lqi)
|
uint8_t lqi)
|
||||||
{
|
{
|
||||||
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||||
|
int beacon_hdr_len;
|
||||||
|
|
||||||
NET_DBG("Beacon received");
|
NET_DBG("Beacon received");
|
||||||
|
|
||||||
|
@ -64,6 +65,10 @@ enum net_verdict ieee802154_handle_beacon(struct net_if *iface,
|
||||||
IEEE802154_EXT_ADDR_LENGTH);
|
IEEE802154_EXT_ADDR_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beacon_hdr_len = ieee802514_beacon_header_length(mpdu->payload, mpdu->payload_length);
|
||||||
|
ctx->scan_ctx->beacon_payload_len = mpdu->payload_length - beacon_hdr_len;
|
||||||
|
ctx->scan_ctx->beacon_payload = (uint8_t *)mpdu->payload + beacon_hdr_len;
|
||||||
|
|
||||||
net_mgmt_event_notify(NET_EVENT_IEEE802154_SCAN_RESULT, iface);
|
net_mgmt_event_notify(NET_EVENT_IEEE802154_SCAN_RESULT, iface);
|
||||||
|
|
||||||
k_sem_give(&ctx->scan_ctx_lock);
|
k_sem_give(&ctx->scan_ctx_lock);
|
||||||
|
|
|
@ -45,12 +45,16 @@ K_SEM_DEFINE(scan_lock, 0, 1);
|
||||||
#define EXPECTED_ENDDEVICE_EXT_ADDR_STR "08:07:06:05:04:03:02:01"
|
#define EXPECTED_ENDDEVICE_EXT_ADDR_STR "08:07:06:05:04:03:02:01"
|
||||||
#define EXPECTED_ENDDEVICE_SHORT_ADDR 0xaaaa
|
#define EXPECTED_ENDDEVICE_SHORT_ADDR 0xaaaa
|
||||||
|
|
||||||
|
#define EXPECTED_PAYLOAD_DATA EXPECTED_ENDDEVICE_EXT_ADDR_LE
|
||||||
|
#define EXPECTED_PAYLOAD_LEN 8
|
||||||
|
|
||||||
static void scan_result_cb(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
|
static void scan_result_cb(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
|
||||||
struct net_if *iface)
|
struct net_if *iface)
|
||||||
{
|
{
|
||||||
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||||
struct ieee802154_req_params *scan_ctx = ctx->scan_ctx;
|
struct ieee802154_req_params *scan_ctx = ctx->scan_ctx;
|
||||||
uint8_t expected_coordinator_address[] = {EXPECTED_COORDINATOR_ADDR_BE};
|
uint8_t expected_coordinator_address[] = {EXPECTED_COORDINATOR_ADDR_BE};
|
||||||
|
uint8_t expected_payload_data[] = {EXPECTED_PAYLOAD_DATA};
|
||||||
|
|
||||||
/* No need for scan_ctx locking as we should execute exclusively. */
|
/* No need for scan_ctx locking as we should execute exclusively. */
|
||||||
|
|
||||||
|
@ -63,6 +67,10 @@ static void scan_result_cb(struct net_mgmt_event_callback *cb, uint32_t mgmt_eve
|
||||||
zassert_equal(scan_ctx->lqi, EXPECTED_COORDINATOR_LQI,
|
zassert_equal(scan_ctx->lqi, EXPECTED_COORDINATOR_LQI,
|
||||||
"Scan did not receive correct link quality indicator.");
|
"Scan did not receive correct link quality indicator.");
|
||||||
|
|
||||||
|
zassert_equal(scan_ctx->beacon_payload_len, EXPECTED_PAYLOAD_LEN,
|
||||||
|
"Scan did not include the payload");
|
||||||
|
zassert_mem_equal(scan_ctx->beacon_payload, expected_payload_data, EXPECTED_PAYLOAD_LEN);
|
||||||
|
|
||||||
k_sem_give(&scan_lock);
|
k_sem_give(&scan_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +209,7 @@ ZTEST(ieee802154_l2_shell, test_active_scan)
|
||||||
0x00, 0xc0, /* Superframe Specification: PAN coordinator + association permitted */
|
0x00, 0xc0, /* Superframe Specification: PAN coordinator + association permitted */
|
||||||
0x00, /* GTS */
|
0x00, /* GTS */
|
||||||
0x00, /* Pending Addresses */
|
0x00, /* Pending Addresses */
|
||||||
0x00, 0x00 /* Payload */
|
EXPECTED_PAYLOAD_DATA /* Layer 3 payload */
|
||||||
};
|
};
|
||||||
struct net_pkt *pkt;
|
struct net_pkt *pkt;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue