diff --git a/impl/src/layer2/connection.c b/impl/src/layer2/connection.c index 8b3ae33..dd09656 100644 --- a/impl/src/layer2/connection.c +++ b/impl/src/layer2/connection.c @@ -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++; } - packet_queue_delete(&ctx->packet_queue, packets_to_remove); + if(packets_to_remove != 0) { + packet_queue_delete(&ctx->packet_queue, packets_to_remove); - packets_available = packet_queue_get_used_space(&ctx->packet_queue); + // 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; - LOG(LVL_DEBUG, "handling ack for seq_nr %u, removed %zu packets, %zu packets remaining.", acked_seq, packets_to_remove, packets_available); + packets_available = packet_queue_get_used_space(&ctx->packet_queue); - ctx->retransmit_time = get_hires_time() + HRTIME_MS(RETRANSMIT_TIMEOUT_MS); + 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 diff --git a/impl/src/layer2/digipeater.c b/impl/src/layer2/digipeater.c index 36f2264..b5de3c7 100644 --- a/impl/src/layer2/digipeater.c +++ b/impl/src/layer2/digipeater.c @@ -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,18 +274,27 @@ 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; - connection_list_entry_t *head = connection_list_get_head(&ctx->conn_list); - if(!head) { - return 0; - } + 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; + } - connection_ctx_t *conn = &head->connection; - if(connection_can_transmit(conn)) { - packet_size = connection_encode_next_packet(conn, buf, buf_len, end_burst); + connection_ctx_t *conn = &head->connection; + if(connection_can_transmit(conn)) { + packet_size = connection_encode_next_packet(conn, buf, buf_len, end_burst); - ctx->state = DIGIPEATER_STATE_CONN; + 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(); - // 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)); + 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); + ctx->state = DIGIPEATER_STATE_CONN; + ctx->interval_end_time = now + HRTIME_MS(MIN_INTERVAL_TIME_MS); + } return OK; } diff --git a/impl/src/layer2/digipeater.h b/impl/src/layer2/digipeater.h index e80917d..664ee01 100644 --- a/impl/src/layer2/digipeater.h +++ b/impl/src/layer2/digipeater.h @@ -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;