mirror of
https://github.com/BotChain-Robots/firmware.git
synced 2026-07-08 09:37:21 +02:00
Fix RIP bugs, add in UART
This commit is contained in:
@@ -27,6 +27,7 @@ void DataLinkManager::init_rip(){
|
||||
rip_table[0].info = {
|
||||
.board_id = this_board_id,
|
||||
.hops = 0,
|
||||
.sum_of_hops = 0,
|
||||
};
|
||||
rip_table[0].channel = MAX_CHANNELS + 1;
|
||||
rip_table[0].ttl = RIP_TTL_START;
|
||||
@@ -37,7 +38,7 @@ void DataLinkManager::init_rip(){
|
||||
start_rip_tasks();
|
||||
}
|
||||
|
||||
esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t channel, RIPRow** entry){
|
||||
esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t sum_of_hops, uint8_t channel, RIPRow** entry){
|
||||
if (entry == nullptr){
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -49,16 +50,16 @@ esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t
|
||||
(*entry)->channel = channel;
|
||||
(*entry)->info = {
|
||||
.board_id = board_id,
|
||||
.hops = hops
|
||||
.hops = hops,
|
||||
.sum_of_hops = sum_of_hops,
|
||||
};
|
||||
(*entry)->ttl = RIP_TTL_START;
|
||||
(*entry)->valid = 1;
|
||||
|
||||
|
||||
// ESP_LOGI(DEBUG_LINK_TAG, "board_id %d now has hops %d from channel %d", (*entry)->info.board_id, (*entry)->info.hops, channel);
|
||||
|
||||
xSemaphoreGive((*entry)->row_sem);
|
||||
|
||||
rip_update_self_sum_of_hops();
|
||||
|
||||
if (uxQueueMessagesWaiting(manual_broadcasts) == 0){
|
||||
bool dummy = true;
|
||||
xQueueSend(manual_broadcasts, &dummy, 0); //new row - send broadcast
|
||||
@@ -67,7 +68,32 @@ esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Recomputes and stores this board's own sum_of_hops (centrality score).
|
||||
* Called whenever the routing table changes. No semaphores are held on entry.
|
||||
*/
|
||||
void DataLinkManager::rip_update_self_sum_of_hops(){
|
||||
uint32_t total = 0;
|
||||
for (size_t i = 1; i < RIP_MAX_ROUTES; i++){
|
||||
if (xSemaphoreTake(rip_table[i].row_sem, pdMS_TO_TICKS(RIP_MAX_SEM_WAIT_MS)) != pdTRUE){
|
||||
continue;
|
||||
}
|
||||
if (rip_table[i].valid == RIP_VALID_ROW && rip_table[i].info.hops <= RIP_MAX_HOPS){
|
||||
total += rip_table[i].info.hops;
|
||||
}
|
||||
xSemaphoreGive(rip_table[i].row_sem);
|
||||
}
|
||||
|
||||
// Clamp to uint8_t max — with RIP_MAX_ROUTES=10 and RIP_MAX_HOPS=15 the max is 9*15=135, fits fine.
|
||||
if (xSemaphoreTake(rip_table[0].row_sem, pdMS_TO_TICKS(RIP_MAX_SEM_WAIT_MS)) == pdTRUE){
|
||||
rip_table[0].info.sum_of_hops = (total > 255) ? 255 : static_cast<uint8_t>(total);
|
||||
xSemaphoreGive(rip_table[0].row_sem);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t DataLinkManager::rip_reset_entry_ttl(uint8_t board_id){
|
||||
// ...existing code...
|
||||
|
||||
RIPRow* entry = nullptr;
|
||||
|
||||
esp_err_t res;
|
||||
@@ -92,7 +118,7 @@ esp_err_t DataLinkManager::rip_reset_entry_ttl(uint8_t board_id){
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t channel, RIPRow** entry){
|
||||
esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t new_sum_of_hops, uint8_t channel, RIPRow** entry){
|
||||
if (entry == nullptr){
|
||||
return ESP_FAIL; //board doesn't exist
|
||||
}
|
||||
@@ -102,22 +128,33 @@ esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t channel, RI
|
||||
}
|
||||
|
||||
uint8_t old_hops = (*entry)->info.hops;
|
||||
uint8_t old_sum_of_hops = (*entry)->info.sum_of_hops;
|
||||
bool hops_improved = (new_hop < (*entry)->info.hops) || ((*entry)->info.hops == RIP_MAX_HOPS + 1);
|
||||
|
||||
if ((*entry)->info.hops >= new_hop && (*entry)->info.hops != RIP_MAX_HOPS + 1){ //no count to infinity if path is invalid
|
||||
if (hops_improved){ //accept better paths and allow recovery from infinity
|
||||
(*entry)->info.hops = new_hop;
|
||||
(*entry)->info.sum_of_hops = new_sum_of_hops;
|
||||
(*entry)->channel = channel;
|
||||
// ESP_LOGI(DEBUG_LINK_TAG, "updated board_id %d now has hops %d from channel %d", (*entry)->info.board_id, (*entry)->info.hops, channel);
|
||||
} else {
|
||||
// Even if hops didn't improve, update the centrality score if it came from the same channel
|
||||
if ((*entry)->channel == channel){
|
||||
(*entry)->info.sum_of_hops = new_sum_of_hops;
|
||||
}
|
||||
}
|
||||
|
||||
(*entry)->ttl = RIP_TTL_START;
|
||||
(*entry)->valid = 1;
|
||||
|
||||
// ESP_LOGI(DEBUG_LINK_TAG, "refreshed board_id %d ttl", (*entry)->info.board_id);
|
||||
bool sum_of_hops_changed = (old_sum_of_hops != (*entry)->info.sum_of_hops);
|
||||
|
||||
xSemaphoreGive((*entry)->row_sem);
|
||||
|
||||
if (uxQueueMessagesWaiting(manual_broadcasts) == 0 && old_hops > new_hop && old_hops != RIP_MAX_HOPS + 1){
|
||||
//if hops were changed, send broadcast (if there isn't already one manual broadcast request pending)
|
||||
if (hops_improved || sum_of_hops_changed){
|
||||
rip_update_self_sum_of_hops();
|
||||
}
|
||||
|
||||
if (uxQueueMessagesWaiting(manual_broadcasts) == 0 && (old_hops > new_hop || old_hops == RIP_MAX_HOPS + 1 || sum_of_hops_changed)){
|
||||
//if hops were changed (or recovered from infinity), or sum_of_hops changed, send broadcast
|
||||
bool dummy = true;
|
||||
xQueueSend(manual_broadcasts, &dummy, 0);
|
||||
}
|
||||
@@ -139,7 +176,7 @@ esp_err_t DataLinkManager::rip_find_entry(uint8_t board_id, RIPRow** entry, bool
|
||||
if (xSemaphoreTake(rip_table[i].row_sem, pdMS_TO_TICKS(RIP_MAX_SEM_WAIT_MS)) != pdTRUE){
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (rip_table[i].valid == RIP_VALID_ROW && rip_table[i].info.board_id == board_id){
|
||||
if ((rip_table[i].valid == RIP_VALID_ROW || rip_table[i].valid == RIP_NEW_ROW) && rip_table[i].info.board_id == board_id){
|
||||
*entry = &rip_table[i];
|
||||
xSemaphoreGive(rip_table[i].row_sem);
|
||||
// ESP_LOGI(DEBUG_LINK_TAG, "Found %d in table at row %d", board_id, i);
|
||||
@@ -198,14 +235,11 @@ esp_err_t DataLinkManager::rip_get_row(RIPRow** entry, uint8_t row_num){
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (rip_table[row_num].info.hops == RIP_MAX_HOPS + 1){
|
||||
//invalid hop, decrement counter
|
||||
rip_table[row_num].ttl_flush--;
|
||||
if (rip_table[row_num].ttl_flush == 0){
|
||||
rip_table[row_num].valid = RIP_INVALID_ROW;
|
||||
xSemaphoreGive(rip_table[row_num].row_sem);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (rip_table[row_num].info.hops == RIP_MAX_HOPS + 1 && rip_table[row_num].ttl_flush == 0){
|
||||
//flush countdown has expired, invalidate the row
|
||||
rip_table[row_num].valid = RIP_INVALID_ROW;
|
||||
xSemaphoreGive(rip_table[row_num].row_sem);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static RIPRow row_snapshots[RIP_MAX_ROUTES];
|
||||
@@ -228,8 +262,7 @@ esp_err_t DataLinkManager::rip_get_row(RIPRow** entry, uint8_t row_num){
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
|
||||
//use the control frame for the demo (as the number of rows increase, we will need to use the generic frame)
|
||||
//data will be [board_id (1), hops (1), board_id (2), hops (2), ...]
|
||||
// Wire format: [board_id (1), hops (1), sum_of_hops (1), ...] (RIP_WIRE_STRIDE bytes per entry)
|
||||
|
||||
uint16_t message_idx = 0;
|
||||
esp_err_t res;
|
||||
@@ -240,7 +273,7 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
|
||||
if(broadcast){
|
||||
for (size_t channel = 0; channel < num_channels; channel++){
|
||||
auto rip_message = std::make_unique<std::vector<uint8_t>>();
|
||||
rip_message->resize(RIP_MAX_ROUTES * 2);
|
||||
rip_message->resize(RIP_MAX_ROUTES * RIP_WIRE_STRIDE);
|
||||
|
||||
for (size_t i = 0; i < RIP_MAX_ROUTES; i++){
|
||||
res = rip_get_row(&entry, i);
|
||||
@@ -253,15 +286,15 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
|
||||
continue;
|
||||
}
|
||||
|
||||
// ESP_LOGI(DEBUG_LINK_TAG, "Found entry for board %d with hops %d", entry->info.board_id, entry->info.hops);
|
||||
|
||||
if (entry->channel == channel){
|
||||
//poisoned reverse
|
||||
rip_message->at(message_idx++) = entry->info.board_id;
|
||||
rip_message->at(message_idx++) = RIP_MAX_HOPS + 1;
|
||||
rip_message->at(message_idx++) = entry->info.sum_of_hops;
|
||||
} else {
|
||||
rip_message->at(message_idx++) = entry->info.board_id;
|
||||
rip_message->at(message_idx++) = entry->info.hops;
|
||||
rip_message->at(message_idx++) = entry->info.sum_of_hops;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +332,7 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
|
||||
}
|
||||
} else {
|
||||
auto rip_message = std::make_unique<std::vector<uint8_t>>();
|
||||
rip_message->resize(RIP_MAX_ROUTES * 2);
|
||||
rip_message->resize(RIP_MAX_ROUTES * RIP_WIRE_STRIDE);
|
||||
|
||||
for (size_t i = 0; i < RIP_MAX_ROUTES; i++){
|
||||
res = rip_get_row(&entry, i);
|
||||
@@ -313,6 +346,7 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
|
||||
}
|
||||
rip_message->data()[message_idx++] = entry->info.board_id;
|
||||
rip_message->data()[message_idx++] = entry->info.hops;
|
||||
rip_message->data()[message_idx++] = entry->info.sum_of_hops;
|
||||
}
|
||||
ESP_LOGI(DEBUG_LINK_TAG, "replying to discovery request to board %d", dest_id);
|
||||
res = send(dest_id, std::move(rip_message), FrameType::RIP_TABLE_CONTROL, FLAG_DISCOVERY);
|
||||
@@ -382,7 +416,7 @@ esp_err_t DataLinkManager::get_routing_table(RIPRow_public* table, size_t* table
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (rip_table[i].valid == RIP_VALID_ROW){
|
||||
table[i].info = rip_table[i].info;
|
||||
table[i].info = rip_table[i].info; // copies board_id, hops, and sum_of_hops
|
||||
table[i].channel = rip_table[i].channel;
|
||||
curr_size++;
|
||||
}
|
||||
@@ -439,15 +473,20 @@ esp_err_t DataLinkManager::get_routing_table(RIPRow_public* table, size_t* table
|
||||
continue;
|
||||
}
|
||||
if (link_layer_obj->rip_table[i].ttl != 0){
|
||||
// link_layer_obj->rip_table[i].valid = RIP_INVALID_ROW;
|
||||
// ESP_LOGI(DEBUG_LINK_TAG, "Entry %d now has ttl %d", i, link_layer_obj->rip_table[i].ttl);
|
||||
// } else {
|
||||
link_layer_obj->rip_table[i].ttl--;
|
||||
if (link_layer_obj->rip_table[i].ttl == 0){
|
||||
link_layer_obj->rip_table[i].info.hops = RIP_MAX_HOPS + 1;
|
||||
link_layer_obj->rip_table[i].ttl_flush = RIP_FLUSH_COUNT;
|
||||
broadcast = true;
|
||||
}
|
||||
} else if (link_layer_obj->rip_table[i].info.hops == RIP_MAX_HOPS + 1){
|
||||
// TTL already zero and route is poisoned — count down the flush timer
|
||||
if (link_layer_obj->rip_table[i].ttl_flush > 0){
|
||||
link_layer_obj->rip_table[i].ttl_flush--;
|
||||
}
|
||||
if (link_layer_obj->rip_table[i].ttl_flush == 0){
|
||||
link_layer_obj->rip_table[i].valid = RIP_INVALID_ROW;
|
||||
}
|
||||
}
|
||||
|
||||
xSemaphoreGive(link_layer_obj->rip_table[i].row_sem);
|
||||
|
||||
Reference in New Issue
Block a user