digipeater: improve beacon handling
This commit is contained in:
parent
8a4619bb0b
commit
c5aa117240
|
@ -449,8 +449,6 @@ void connection_handle_ack(connection_ctx_t *ctx, uint8_t acked_seq, bool do_ack
|
|||
break;
|
||||
}
|
||||
|
||||
ctx->next_packet_index = 0;
|
||||
|
||||
size_t packets_to_remove = 0;
|
||||
size_t packets_available = packet_queue_get_used_space(&ctx->packet_queue);
|
||||
|
||||
|
@ -464,13 +462,21 @@ void connection_handle_ack(connection_ctx_t *ctx, uint8_t acked_seq, bool do_ack
|
|||
packets_to_remove++;
|
||||
}
|
||||
|
||||
if(packets_to_remove != 0) {
|
||||
packet_queue_delete(&ctx->packet_queue, packets_to_remove);
|
||||
|
||||
// send the next requested packet (all previous ones were deleted above).
|
||||
assert(ctx->next_packet_index >= packets_to_remove);
|
||||
ctx->next_packet_index -= packets_to_remove;
|
||||
|
||||
packets_available = packet_queue_get_used_space(&ctx->packet_queue);
|
||||
|
||||
LOG(LVL_DEBUG, "handling ack for seq_nr %u, removed %zu packets, %zu packets remaining.", acked_seq, packets_to_remove, packets_available);
|
||||
|
||||
ctx->retransmit_time = get_hires_time() + HRTIME_MS(RETRANSMIT_TIMEOUT_MS);
|
||||
} else {
|
||||
LOG(LVL_DEBUG, "duplicate ACK for seq_nr %u", acked_seq);
|
||||
}
|
||||
|
||||
if(do_ack && packets_available == 0) {
|
||||
// no packets left in queue, but an acknowledgement must be
|
||||
|
|
|
@ -79,6 +79,25 @@ static result_t digipeater_handle_beacon_responses(digipeater_ctx_t *ctx, const
|
|||
}
|
||||
|
||||
|
||||
static size_t encode_beacon_packet(digipeater_ctx_t *ctx, uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
// build a beacon packet
|
||||
layer2_packet_header_t header;
|
||||
|
||||
ham64_t broadcast = {{0xFFFF, 0, 0, 0}, 1};
|
||||
|
||||
header.dst_addr = broadcast;
|
||||
header.src_addr = ctx->my_addr;
|
||||
header.msg_type = L2_MSG_TYPE_CONN_MGMT;
|
||||
header.rx_seq_nr = 0; // unused
|
||||
header.tx_seq_nr = 0; // unused
|
||||
header.tx_request = 1;
|
||||
|
||||
uint8_t payload[1] = {CONN_MGMT_TYPE_BEACON};
|
||||
return layer2_encode_packet(&header, payload, 1, buf, buf_len);
|
||||
}
|
||||
|
||||
|
||||
result_t digipeater_init(digipeater_ctx_t *ctx, const ham64_t *my_addr, digipeater_data_callback_t data_cb)
|
||||
{
|
||||
ctx->my_addr = *my_addr;
|
||||
|
@ -239,31 +258,11 @@ result_t digipeater_fill_packet_queues_from_tundev(digipeater_ctx_t *ctx, int tu
|
|||
size_t digipeater_encode_next_packet(digipeater_ctx_t *ctx, uint8_t *buf, size_t buf_len, bool *end_burst)
|
||||
{
|
||||
uint64_t now = get_hires_time();
|
||||
|
||||
size_t packet_size = 0;
|
||||
|
||||
*end_burst = false;
|
||||
|
||||
if(now > ctx->next_beacon_time) {
|
||||
// build a beacon packet
|
||||
layer2_packet_header_t header;
|
||||
|
||||
ham64_t broadcast = {{0xFFFF, 0, 0, 0}, 1};
|
||||
|
||||
header.dst_addr = broadcast;
|
||||
header.src_addr = ctx->my_addr;
|
||||
header.msg_type = L2_MSG_TYPE_CONN_MGMT;
|
||||
header.rx_seq_nr = 0; // unused
|
||||
header.tx_seq_nr = 0; // unused
|
||||
header.tx_request = 1;
|
||||
|
||||
uint8_t payload[1] = {CONN_MGMT_TYPE_BEACON};
|
||||
packet_size = layer2_encode_packet(&header, payload, 1, buf, buf_len);
|
||||
|
||||
ctx->state = DIGIPEATER_STATE_BEACON;
|
||||
*end_burst = true;
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
// send packets from the one-shot queue
|
||||
const packet_queue_entry_t *queue_entry = packet_queue_get(&ctx->oneshot_queue, 0);
|
||||
if(queue_entry) {
|
||||
|
@ -275,8 +274,14 @@ size_t digipeater_encode_next_packet(digipeater_ctx_t *ctx, uint8_t *buf, size_t
|
|||
}
|
||||
}
|
||||
|
||||
// pull packets from the current connection
|
||||
switch(ctx->state) {
|
||||
case DIGIPEATER_STATE_BEACON:
|
||||
packet_size = encode_beacon_packet(ctx, buf, buf_len);
|
||||
*end_burst = true;
|
||||
break;
|
||||
|
||||
case DIGIPEATER_STATE_CONN: {
|
||||
// pull packets from the current connection
|
||||
connection_list_entry_t *head = connection_list_get_head(&ctx->conn_list);
|
||||
if(!head) {
|
||||
return 0;
|
||||
|
@ -288,6 +293,9 @@ size_t digipeater_encode_next_packet(digipeater_ctx_t *ctx, uint8_t *buf, size_t
|
|||
|
||||
ctx->state = DIGIPEATER_STATE_CONN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return packet_size;
|
||||
}
|
||||
|
@ -301,6 +309,10 @@ bool digipeater_can_transmit(digipeater_ctx_t *ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
if(packet_queue_get_used_space(&ctx->oneshot_queue) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
connection_list_entry_t *head = connection_list_get_head(&ctx->conn_list);
|
||||
if(head) {
|
||||
return connection_can_transmit(&head->connection);
|
||||
|
@ -320,12 +332,17 @@ result_t digipeater_end_interval(digipeater_ctx_t *ctx)
|
|||
{
|
||||
uint64_t now = get_hires_time();
|
||||
|
||||
if(now >= ctx->next_beacon_time) {
|
||||
ctx->next_beacon_time += HRTIME_MS(BEACON_INTERVAL_MS);
|
||||
ctx->state = DIGIPEATER_STATE_BEACON;
|
||||
} else {
|
||||
// TODO: adjust the time based on connection activity; right now this results
|
||||
// in round-robin scheduling
|
||||
connection_list_reschedule_head(&ctx->conn_list, now + HRTIME_MS(MIN_INTERVAL_TIME_MS));
|
||||
|
||||
ctx->state = DIGIPEATER_STATE_CONN;
|
||||
ctx->interval_end_time = now + HRTIME_MS(MIN_INTERVAL_TIME_MS);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ typedef enum {
|
|||
} digipeater_state_t;
|
||||
|
||||
typedef enum {
|
||||
// FIXME: rename to Cycle
|
||||
DIGIPEATER_EVT_INTERVAL_END, //!< The current interval has ended and new packets should be transmitted.
|
||||
} digipeater_evt_t;
|
||||
|
||||
|
|
Loading…
Reference in a new issue