diff --git a/src/algo_lightning.c b/src/algo_lightning.c index 556c8ba..c3a3f5b 100644 --- a/src/algo_lightning.c +++ b/src/algo_lightning.c @@ -40,6 +40,18 @@ char* schedule_group_target_str[] = { "SCHEDULE_SLOW" }; +enum link_cat { + LINK_FAST = 0, + LINK_SLOW = 1, + LINK_NOT_USED = 2 +}; + +char* link_cat_str[] = { + "LINK_FAST", + "LINK_SLOW", + "LINK_NOT_USED" +}; + struct stat_entry { uint8_t link_id; int64_t ooo; @@ -56,7 +68,7 @@ struct timing_entry { struct link_status { struct timespec last; - uint8_t used; + enum link_cat used; }; struct light_ctx { @@ -80,6 +92,7 @@ struct light_ctx { int is_measlat; int explain; int disable_scheduler; + struct stat_entry stats[MAX_LINKS]; enum schedule_group_target sched_strat; }; @@ -130,8 +143,8 @@ void algo_lightning_init(struct evt_core_ctx* ctx, struct algo_ctx* app_ctx, str lightc->prev_links[i] = UINT8_MAX; lightc->used = lightc->fast_count * 2; - for (int i = 0; i < lightc->used; i++) { - lightc->status[i].used = 1; + for (int i = 0; i < lightc->total_links; i++) { + lightc->status[i].used = i < lightc->used ? LINK_SLOW : LINK_NOT_USED; } union abstract_packet m; @@ -286,16 +299,16 @@ int compare_stat_entry_max(const void *a, const void *b) { return sea->ooo - seb->ooo; } -void algo_lightning_update_stats (struct light_ctx *lightc, struct stat_entry *stats) { +void algo_lightning_update_stats (struct light_ctx *lightc) { struct timespec now, not_before = {0}, temp_time; set_now(&now); timespec_diff (&now, &lightc->window, ¬_before); // Init for (int i = 0; i < lightc->total_links; i++) { - stats[i].link_id = i; - stats[i].meas_occ = 0; - stats[i].ooo = -1; + lightc->stats[i].link_id = i; + lightc->stats[i].meas_occ = 0; + lightc->stats[i].ooo = -1; } // Compute local stats @@ -310,19 +323,19 @@ void algo_lightning_update_stats (struct light_ctx *lightc, struct stat_entry *s case OOO_ONGOING: timespec_diff(&now, &lightc->historic[i].detected_at, &temp_time); delta = timespec_get_unit (&temp_time, MILISEC); - stats[l].ooo += delta; - stats[l].meas_occ += 1; + lightc->stats[l].ooo += delta; + lightc->stats[l].meas_occ += 1; break; case OOO_DONE: timespec_diff(&lightc->historic[i].finished_at, &lightc->historic[i].detected_at, &temp_time); delta = timespec_get_unit (&temp_time, MILISEC); - stats[l].ooo += delta; - stats[l].meas_occ += 1; + lightc->stats[l].ooo += delta; + lightc->stats[l].meas_occ += 1; break; } if (lightc->explain) printf("(stats.compute) packet=%ld, link=%d, status=%s, delta=%ld\n", lightc->historic[i].pkt_id, l, ooo_state_str[lightc->historic[i].state], delta); - stats[l].link_id = l; + lightc->stats[l].link_id = l; if (lightc->explain) printf("(stats.local) link=%d, delta=%ld\n", l, delta); /*if (delta > stats[l].ooo) { @@ -333,16 +346,16 @@ void algo_lightning_update_stats (struct light_ctx *lightc, struct stat_entry *s // Compute average for (int i = 0; i < lightc->total_links; i++) { - if (stats[i].meas_occ <= 0) continue; - stats[i].ooo = stats[i].ooo / stats[i].meas_occ; + if (lightc->stats[i].meas_occ <= 0) continue; + lightc->stats[i].ooo = lightc->stats[i].ooo / lightc->stats[i].meas_occ; } // Set my local stats + merge remote stats for (int i = 0; i < lightc->total_links; i++) { - lightc->local_stats[i] = stats[i].ooo; + lightc->local_stats[i] = lightc->stats[i].ooo; if (lightc->remote_stats[i] == -1) continue; - if (stats[i].ooo == -1) stats[i].ooo = lightc->remote_stats[i]; - else stats[i].ooo = (lightc->remote_stats[i] + stats[i].ooo) / 2; + if (lightc->stats[i].ooo == -1) lightc->stats[i].ooo = lightc->remote_stats[i]; + else lightc->stats[i].ooo = (lightc->remote_stats[i] + lightc->stats[i].ooo) / 2; /* if (lightc->remote_stats[i] > stats[i].ooo) { if (lightc->explain) printf("(stats.remote) link=%d, delta=%d\n", i, lightc->remote_stats[i]); @@ -352,7 +365,7 @@ void algo_lightning_update_stats (struct light_ctx *lightc, struct stat_entry *s // Sort if (!lightc->disable_scheduler) { - qsort(stats, lightc->total_links, sizeof(struct stat_entry), compare_stat_entry_max); + qsort(lightc->stats, lightc->total_links, sizeof(struct stat_entry), compare_stat_entry_max); } } @@ -429,43 +442,56 @@ void tag_packet_measlat(union abstract_packet* ap, uint8_t link_id, uint8_t is_s } } -void algo_lightning_update_used(struct light_ctx *lightc, struct stat_entry *stats, struct timespec *now) { +void algo_lightning_update_used(struct light_ctx *lightc, struct timespec *now) { struct timespec not_before = {0}, oldest = *now; timespec_diff(now, &lightc->window, ¬_before); if (timespec_gt(&lightc->last_update_used, ¬_before)) return; - printf("update triggered\n"); - int used_to_not = 0, not_to_used = 0; int64_t max_ooo = 0; for (int i = 0; i < lightc->total_links; i++) { - if (lightc->status[stats[i].link_id].used) { - if (stats[i].ooo >= max_ooo) { - max_ooo = stats[i].ooo; - used_to_not = stats[i].link_id; + if (lightc->status[lightc->stats[i].link_id].used == LINK_FAST || lightc->status[lightc->stats[i].link_id].used == LINK_SLOW) { + int64_t retained_ooo = lightc->stats[i].ooo == -1 ? INT64_MAX : lightc->stats[i].ooo; + if (retained_ooo >= max_ooo) { + max_ooo = retained_ooo; + used_to_not = lightc->stats[i].link_id; } } else { - if (timespec_lt(&lightc->status[stats[i].link_id].last, &oldest)) { - oldest = lightc->status[stats[i].link_id].last; - not_to_used = stats[i].link_id; + if (timespec_lt(&lightc->status[lightc->stats[i].link_id].last, &oldest)) { + oldest = lightc->status[lightc->stats[i].link_id].last; + not_to_used = lightc->stats[i].link_id; } } } // Do we have a good link not used? for (int i = 0; i < lightc->used; i++) { - if (!lightc->status[stats[i].link_id].used) { - not_to_used = stats[i].link_id; + if (lightc->status[lightc->stats[i].link_id].used == LINK_NOT_USED) { + not_to_used = lightc->stats[i].link_id; break; } } // Swap them - lightc->status[used_to_not].used = 0; - lightc->status[not_to_used].used = 1; + printf("Link %d will be disabled, %d will be enabled\n", used_to_not, not_to_used); + lightc->status[used_to_not].used = LINK_NOT_USED; + lightc->status[not_to_used].used = LINK_SLOW; lightc->last_update_used = *now; } +void algo_lightning_link_cat(struct light_ctx *lightc) { + uint8_t used = 0; + printf("---\n"); + for (int i = 0; i < lightc->total_links; i++) { + if (lightc->status[lightc->stats[i].link_id].used != LINK_NOT_USED) { + if (used < lightc->fast_count) lightc->status[lightc->stats[i].link_id].used = LINK_FAST; + else lightc->status[lightc->stats[i].link_id].used = LINK_SLOW; + used++; + } + printf("Link ID=%d, status=%s, ooo=%ld\n", lightc->stats[i].link_id, link_cat_str[lightc->status[lightc->stats[i].link_id].used], lightc->stats[i].ooo); + } +} + int algo_lightning_on_datagram(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo, struct buffer_packet* bp) { struct algo_ctx* app_ctx = fdinfo->cat->app_ctx; struct light_ctx* lightc = app_ctx->misc; @@ -477,14 +503,14 @@ int algo_lightning_on_datagram(struct evt_core_ctx* ctx, struct evt_core_fdinfo* algo_lightning_pad (ctx, fdinfo, bp); // Compute stats - struct stat_entry stats[MAX_LINKS] = {0}; - algo_lightning_update_stats(lightc, stats); - algo_lightning_update_used(lightc, stats, &now); + algo_lightning_update_stats(lightc); + algo_lightning_update_used(lightc, &now); + algo_lightning_link_cat(lightc); if (ctx->verbose > 1) { printf("after sort: "); for (int i = 0; i < lightc->total_links; i++) { - printf("%d (%ld), ", stats[i].link_id, stats[i].ooo); + printf("%d (%ld), ", lightc->stats[i].link_id, lightc->stats[i].ooo); } printf("\n"); } @@ -496,12 +522,11 @@ int algo_lightning_on_datagram(struct evt_core_ctx* ctx, struct evt_core_fdinfo* sel_link_last = now; lightc->selected_link = UINT8_MAX; for (int i = 0, j = 0; i < lightc->total_links && j < lightc->fast_count; i++) { - if (!lightc->status[stats[i].link_id].used) continue; - if (timespec_lt (&lightc->status[stats[i].link_id].last, &sel_link_last)) { - lightc->selected_link = stats[i].link_id; - sel_link_last = lightc->status[stats[i].link_id].last; + if (lightc->status[lightc->stats[i].link_id].used != LINK_FAST) continue; + if (timespec_lt (&lightc->status[lightc->stats[i].link_id].last, &sel_link_last)) { + lightc->selected_link = lightc->stats[i].link_id; + sel_link_last = lightc->status[lightc->stats[i].link_id].last; } - j++; } if (lightc->is_measlat) tag_packet_measlat (ap, lightc->selected_link, 0); send_message (ctx, bp); @@ -512,13 +537,12 @@ int algo_lightning_on_datagram(struct evt_core_ctx* ctx, struct evt_core_fdinfo* if (lightc->sched_strat == SCHEDULE_BOTH || lightc->sched_strat == SCHEDULE_SLOW) { sel_link_last = now; lightc->selected_link = UINT8_MAX; - for (int i = lightc->total_links-1, j = 0; i >= 0 && j < lightc->fast_count; i++) { - if (!lightc->status[stats[i].link_id].used) continue; - if (timespec_lt (&lightc->status[stats[i].link_id].last, &sel_link_last)) { - lightc->selected_link = stats[i].link_id; - sel_link_last = lightc->status[stats[i].link_id].last; + for (int i = 0; i < lightc->total_links; i++) { + if (lightc->status[lightc->stats[i].link_id].used != LINK_SLOW) continue; + if (timespec_lt (&lightc->status[lightc->stats[i].link_id].last, &sel_link_last)) { + lightc->selected_link = lightc->stats[i].link_id; + sel_link_last = lightc->status[lightc->stats[i].link_id].last; } - j++; } if (lightc->is_measlat) tag_packet_measlat (ap, lightc->selected_link, 1); send_message (ctx, bp);