Skip to content

Commit

Permalink
Check MAC status when purging indirect queue (ARMmbed#1811)
Browse files Browse the repository at this point in the history
When more room is needed for indirect messages then old messages are
purged from MAC. If MAC is already processing a message then it can
not be freed. Check MAC return value to avoid freeing message that is
under processing.

Update MPX API to return non-zero value in case of data purging fails.
  • Loading branch information
Arto Kinnunen authored Sep 10, 2018
1 parent 6fe5ea5 commit a40e012
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 37 deletions.
3 changes: 2 additions & 1 deletion nanostack/mac_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,9 @@ typedef void mcps_data_request_ext(const mac_api_t* api, const mcps_data_req_t *
* @brief mcps_purge_request MCPS_PURGE request call
* @param api API to handle the request
* @param data MCPS-PURGE.request specific values
* @return 0 in case of success, non-zero otherwise
*/
typedef void mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data);
typedef uint8_t mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data);

//Upper layer specific callback functions (will also be set by Upper layer after mac_api_t has been created and given to it)

Expand Down
3 changes: 2 additions & 1 deletion source/6LoWPAN/MAC/mpx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s
* @param api API to handle the request
* @param purge MCPS-purge request
* @param user_id MPX user ID
* @return 0 if purge requst was OK, non-zero otherwise
*
*/
typedef void mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);
typedef uint8_t mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);

/**
* @brief mpx_data_confirm MPX-DATA confirm is called as a response to MPX-DATA request
Expand Down
52 changes: 37 additions & 15 deletions source/6LoWPAN/adaptation_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ typedef struct {
bool fragmented_data:1;
bool first_fragment:1;
bool indirect_data:1;
bool indirect_data_cached:1; /* Data cached for delayed transmission as mac request is already active */
bool indirect_data_cached:1; /*!< Data cached for delayed transmission as mac request is already active */
buffer_t *buf;
uint8_t *fragmenter_buf;
ns_list_link_t link; /*!< List link entry */
Expand Down Expand Up @@ -131,7 +131,7 @@ static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr);
/* Fragmentation local functions */
static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr);
static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq);
static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);

static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);

Expand Down Expand Up @@ -749,7 +749,7 @@ static bool lowpan_adaptation_indirect_cache_trigger(protocol_interface_info_ent
ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) {
if (fragmenter_tx_entry->indirect_data_cached) {
if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) {
tr_debug_extra("pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address));
tr_debug_extra("Pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address));
fragmenter_tx_entry->indirect_data_cached = false;
lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr);
return true;
Expand Down Expand Up @@ -799,7 +799,12 @@ static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info
mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type);
if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) {
if (++count >= interface_ptr->max_indirect_small_packets_per_child) {
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry);
tr_debug_extra("Purge seq: %d", tx_entry->buf->seq);
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) {
/* entry could not be purged from mac, try next entry */
tr_debug_extra("Purge failed, try next");
count--;
}
}
}
}
Expand All @@ -816,8 +821,12 @@ static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface
ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) {
if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) {
if (++count >= interface_ptr->max_indirect_big_packets_total) {
tr_debug_extra("free seq: %d", tx_entry->buf->seq);
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry);
tr_debug_extra("Purge seq: %d", tx_entry->buf->seq);
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) {
tr_debug("Purge failed, try next entry");
/* entry could not be purged from mac, try next entry */
count--;
}
}
}
}
Expand Down Expand Up @@ -1275,29 +1284,44 @@ static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *addres
return true;
}

static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle)
static bool lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle)
{
mcps_purge_t purge_req;
purge_req.msduHandle = msduhandle;
bool mac_purge_success = false;
if (interface_ptr->mpx_api) {
interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id);
if (interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id) == 0) {
mac_purge_success = true;
}
} else {
if (cur->mac_api->mcps_purge_req) {
cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req);
if (cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req) == 0) {
mac_purge_success = true;
}
}
}

return mac_purge_success;
}

static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr)
static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr)
{
tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq);
lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq);
tr_debug("Purge from indirect handle %u, cached %d", tx_ptr->buf->seq, tx_ptr->indirect_data_cached);
if (tx_ptr->indirect_data_cached == false) {
if (lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq) == false) {
// MAC purge failed
return false;
}
}

lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL);

return true;
}

void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr)
{
//Free firts by defined short address
//Free first by defined short address
if (entry_ptr->mac16 < 0xfffe) {
uint8_t temp_address[2];
common_write_16_bit(entry_ptr->mac16, temp_address);
Expand All @@ -1317,15 +1341,13 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr

//Check first indirect queue
ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) {

if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) {
//Purge from mac
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry);
}
}

return 0;

}

int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child)
Expand Down
16 changes: 10 additions & 6 deletions source/6LoWPAN/ws/ws_llc_data_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id);
static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id);
static int8_t ws_llc_mpx_data_cb_register(const mpx_api_t* api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id);
static uint16_t ws_llc_mpx_header_size_get(const mpx_api_t * api, uint16_t user_id);
static void ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);
static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);
static void ws_llc_mpx_init(mpx_class_t *mpx_class);

/** Discover Message by message handle id */
Expand Down Expand Up @@ -734,22 +734,26 @@ static uint16_t ws_llc_mpx_header_size_get(const mpx_api_t * api, uint16_t user_
return ws_mpx_header_size_get(base, user_id);
}

static void ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id)
static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id)
{
llc_data_base_t *base = ws_llc_discover_by_mpx(api);
if (!base) {
return;
return MLME_INVALID_HANDLE;
}
llc_message_t * message = llc_message_discover_mpx_user_id(purge->msduHandle,user_id, &base->llc_message_list);
if (!message) {
return;
return MLME_INVALID_HANDLE;
}

mcps_purge_t purge_req;
uint8_t purge_status;
purge_req.msduHandle = message->msg_handle;
llc_message_free(message, base);
base->interface_ptr->mac_api->mcps_purge_req(base->interface_ptr->mac_api, &purge_req);
purge_status = base->interface_ptr->mac_api->mcps_purge_req(base->interface_ptr->mac_api, &purge_req);
if (purge_status == 0) {
llc_message_free(message, base);
}

return purge_status;
}

static void ws_llc_mpx_init(mpx_class_t *mpx_class)
Expand Down
11 changes: 5 additions & 6 deletions source/MAC/IEEE802_15_4/mac_mcps_sap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2234,17 +2234,14 @@ static bool mcps_sap_purge_req_from_queue(protocol_interface_rf_mac_setup_s *rf_
uint8_t status = false;
rf_mac_setup->pd_data_request_queue_to_go = mcps_sap_purge_from_list(rf_mac_setup->pd_data_request_queue_to_go, msduhandle, &status);

if (status) {
return true;
if (!status) {
rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status);
}

rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status);

return status;

}

void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req)
uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req)
{
mcps_purge_conf_t confirmation;
confirmation.msduHandle = purge_req->msduHandle;
Expand All @@ -2258,4 +2255,6 @@ void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup,
if( get_sw_mac_api(rf_mac_setup) ) {
get_sw_mac_api(rf_mac_setup)->purge_conf_cb(get_sw_mac_api(rf_mac_setup), &confirmation);
}

return confirmation.status;
}
2 changes: 1 addition & 1 deletion source/MAC/IEEE802_15_4/mac_mcps_sap.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ int mac_convert_frame_type_to_fhss(uint8_t frame_type);

void mcps_sap_trig_tx(void *mac_ptr);

void mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req);
uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req);

int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);

Expand Down
7 changes: 4 additions & 3 deletions source/MAC/IEEE802_15_4/sw_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication
static void mlme_req(const mac_api_t* api, mlme_primitive id, const void *data);
static void mcps_req(const mac_api_t* api, const mcps_data_req_t *data);
static void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list);
static void purge_req(const mac_api_t* api, const mcps_purge_t *data);
static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data);
static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64);
static int8_t macext_mac64_address_get( const mac_api_t* api, mac_extended_address_type type, uint8_t *mac64_buf);

Expand Down Expand Up @@ -510,11 +510,12 @@ void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_
}


static void purge_req(const mac_api_t* api, const mcps_purge_t *data)
static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data)
{
if (mac_store.mac_api == api) {
mcps_sap_purge_reg_handler(mac_store.setup , data );
return mcps_sap_purge_reg_handler(mac_store.setup , data );
}
return MLME_INVALID_HANDLE;
}

static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ static void mcps_data_req_cb(const mac_api_t* api, const mcps_data_req_t *data)
mcps_data_req_cnt++;
}

static void tester_mcps_purge_request(const mac_api_t* api,
static uint8_t tester_mcps_purge_request(const mac_api_t* api,
const mcps_purge_t *data)
{
(void) api;
(void) data;
mcps_purge_req_cnt++;
return 0;
}

bool test_lowpan_adaptation_interface_init()
Expand Down Expand Up @@ -680,8 +681,8 @@ bool test_lowpan_adaptation_interface_indirect_tx()
if (0 != lowpan_adaptation_interface_tx(&entry, test_buf2)) {
return false;
} else if ((data_request_count != mcps_data_req_cnt) ||
(++data_purge_count != mcps_purge_req_cnt)) {
// error if mac data request sent or no purging
(data_purge_count != mcps_purge_req_cnt)) {
// error if mac data request sent or purging
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion test/nanostack/unittest/stub/mac_mcps_sap_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ void mcps_sap_trig_tx(void *mac_ptr)
{
}

void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *data)
uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *data)
{
return 0;
}

int mac_convert_frame_type_to_fhss(uint8_t frame_type)
Expand Down

0 comments on commit a40e012

Please sign in to comment.