From: pcarana Date: Fri, 3 May 2019 21:14:40 +0000 (-0500) Subject: Merge remote-tracking branch 'origin/cleanup' into roa-hashtable X-Git-Tag: v0.0.2~41 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8b2441d452bb27b4061e816362116c884c77b65d;p=thirdparty%2FFORT-validator.git Merge remote-tracking branch 'origin/cleanup' into roa-hashtable --- 8b2441d452bb27b4061e816362116c884c77b65d diff --cc src/rtr/db/vrps.c index 14038ced,d6160ab7..9e3e0882 --- a/src/rtr/db/vrps.c +++ b/src/rtr/db/vrps.c @@@ -3,9 -3,11 +3,12 @@@ #include #include #include +#include "clients.h" #include "common.h" + #include "validation_handler.h" #include "data_structure/array_list.h" + #include "object/tal.h" + #include "rtr/db/roa_table.h" /* * Storage of VRPs (term taken from RFC 6811 "Validated ROA Payload") and @@@ -80,33 -91,114 +92,162 @@@ vrps_destroy(void pthread_rwlock_destroy(&lock); /* Nothing to do with error code */ } - /* - * @new_deltas can be NULL, @new_tree cannot. + static int + __reset(void *arg) + { + return rtrhandler_reset(arg); + } + + int + __handle_roa_v4(uint32_t as, struct ipv4_prefix const *prefix, + uint8_t max_length, void *arg) + { + return rtrhandler_handle_roa_v4(arg, as, prefix, max_length); + } + + int + __handle_roa_v6(uint32_t as, struct ipv6_prefix const * prefix, + uint8_t max_length, void *arg) + { + return rtrhandler_handle_roa_v6(arg, as, prefix, max_length); + } + + static int + __perform_standalone_validation(struct roa_table **result) + { + struct roa_table *roas; + struct validation_handler validation_handler; + int error; + + roas = roa_table_create(); + if (roas == NULL) + return pr_enomem(); + + validation_handler.reset = __reset; + validation_handler.traverse_down = NULL; + validation_handler.traverse_up = NULL; + validation_handler.handle_roa_v4 = __handle_roa_v4; + validation_handler.handle_roa_v6 = __handle_roa_v6; + validation_handler.arg = roas; + + error = perform_standalone_validation(&validation_handler); + if (error) { + roa_table_destroy(roas); + return error; + } + + *result = roas; + return 0; + } + ++ ++ ++/** ++ * Reallocate the array of @db starting at @start, the length and capacity are ++ * calculated according to the new start. + */ ++static void ++resize_deltas_db(struct deltas_db *db, struct delta *start) ++{ ++ struct delta *tmp; ++ ++ db->len -= (start - db->array); ++ while (db->len < db->capacity / 2) ++ db->capacity /= 2; ++ tmp = malloc(sizeof(struct delta) * db->capacity); ++ if (tmp == NULL) { ++ pr_enomem(); ++ return; ++ } ++ memcpy(tmp, start, db->len * sizeof(struct delta)); ++ free(db->array); ++ db->array = tmp; ++} ++ ++static void ++vrps_purge(void) ++{ ++ struct delta *d; ++ uint32_t min_serial; ++ ++ min_serial = clients_get_min_serial(); ++ ++ /** Assume is ordered by serial, so get the new initial pointer */ ++ ARRAYLIST_FOREACH(&state.deltas, d) ++ if (d->serial >= min_serial) ++ break; ++ ++ /** Is the first element or reached end, nothing to purge */ ++ if (d == state.deltas.array || ++ (d - state.deltas.array) == state.deltas.len) ++ return; ++ ++ resize_deltas_db(&state.deltas, d); ++} ++ int - vrps_update(struct roa_table *new_roas, struct deltas *new_deltas) + vrps_update(bool *changed) { - struct delta new_delta; - int error = 0; + struct roa_table *old_base; + struct roa_table *new_base; + struct deltas *deltas; /* Deltas in raw form */ + struct delta deltas_node; /* Deltas in database node form */ + int error; + + *changed = false; + old_base = NULL; + new_base = NULL; + + error = __perform_standalone_validation(&new_base); + if (error) + return error; rwlock_write_lock(&lock); - if (new_deltas != NULL) { - new_delta.serial = state.current_serial; - new_delta.deltas = new_deltas; - error = deltas_db_add(&state.deltas, &new_delta); - if (error) - goto end; + if (state.base != NULL) { + error = compute_deltas(state.base, new_base, &deltas); + if (error) { + rwlock_unlock(&lock); + goto revert_base; + } + + if (deltas_is_empty(deltas)) { + rwlock_unlock(&lock); + goto revert_deltas; /* error == 0 is good */ + } + - deltas_node.serial = state.current_serial + 1; ++ deltas_node.serial = state.current_serial; + deltas_node.deltas = deltas; + error = deltas_db_add(&state.deltas, &deltas_node); + if (error) { + rwlock_unlock(&lock); + goto revert_deltas; + } + + /* + * Postpone destruction of the old database, + * to release the lock ASAP. + */ + old_base = state.base; ++ ++ /** Remove unnecessary deltas */ ++ vrps_purge(); } - if (state.base != NULL) - roa_table_put(state.base); - state.base = new_roas; - roa_table_get(new_roas); + *changed = true; + state.base = new_base; state.current_serial++; - end: rwlock_unlock(&lock); + + if (old_base != NULL) + roa_table_destroy(old_base); + return 0; + + revert_deltas: + deltas_destroy(deltas); + revert_base: + roa_table_destroy(new_base); return error; }