]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Merge remote-tracking branch 'origin/cleanup' into roa-hashtable
authorpcarana <pc.moreno2099@gmail.com>
Fri, 3 May 2019 21:14:40 +0000 (16:14 -0500)
committerpcarana <pc.moreno2099@gmail.com>
Fri, 3 May 2019 21:14:40 +0000 (16:14 -0500)
1  2 
src/rtr/db/vrps.c

index 14038ced85b478b9bc1a79740c6661432639e7bb,d6160ab762b8d14577f2cd0493d49481fbbf568b..9e3e0882736a5ab7eb179bb5d8ec521e1a1ebd2c
@@@ -3,9 -3,11 +3,12 @@@
  #include <pthread.h>
  #include <stdbool.h>
  #include <string.h>
 +#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;
  }