This commit does two things to improve how prefixes are stored in the
database:
 1. For ROAs, switch from a single, very large cell per ROA to a
    separate table with one row per prefix. This removes an upper
    bound on the number of prefixes per ROA.
 2. For all prefixes, switch from a textual format to a simple binary
    format.

WARNING: This commit only updates the schema, it does not update any
of the code that relies on the schema. As such, this commit breaks a
lot of code. Subsequent commit(s) will update that code to work again.

addresses [#6] and [#7]
---
 bin/rpki/upgrade.in | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/rpki/scmmain.h  | 54 +++++++++++++++++++++++++++-----
 2 files changed, 134 insertions(+), 8 deletions(-)

diff --git a/bin/rpki/upgrade.in b/bin/rpki/upgrade.in
index 1ecfb57..9e93a5c 100644
--- a/bin/rpki/upgrade.in
+++ b/bin/rpki/upgrade.in
@@ -52,10 +52,92 @@ show_msgs () {
 }
 
 
-upgrade_from_0_9 () {
+upgrade_from_0_10 () {
+    log "Clearing rpki-rtr data before altering schema."
+    rpki-rtr-clear -f || fatal "Could not clear rpki-rtr data."
+
+    log "Removing all ROAs from the database before altering schema."
+    RPKICacheDir=$(try config_get RPKICacheDir) || exit 1
+    find "${RPKICacheDir}" -type f -name \*.roa -exec sh -c '
+             ret=0
+             for f in "$@"; do
+                 rcli -d "${f}" || ret=1
+             done
+             exit "${ret}"
+         ' - '{}' + \
+         || add_msg "\
+Potentially failed to remove all ROA files before upgrading the
+database schema. This is probably not a problem."
+
+    log "Updating the database schema."
+    mysql_cmd <<\EOF || fatal "Could not update the database schema."
+ALTER TABLE rpki_roa DROP COLUMN ip_addrs;
+
+CREATE TABLE rpki_roa_prefix (
+    roa_local_id INT UNSIGNED NOT NULL,
+    prefix VARBINARY(16) NOT NULL,
+    prefix_length TINYINT UNSIGNED NOT NULL,
+    prefix_max_length TINYINT UNSIGNED NOT NULL,
+    KEY (roa_local_id, prefix),
+    FOREIGN KEY (roa_local_id) REFERENCES rpki_roa (local_id)
+        ON DELETE CASCADE
+        ON UPDATE CASCADE,
+    CHECK (length(prefix) = 4 OR length(prefix) = 16),
+    CHECK (prefix_length <= prefix_max_length),
+    CHECK (prefix_max_length <= length(prefix) * 8));
+
+ALTER TABLE rtr_full
+    DROP PRIMARY KEY,
+    DROP COLUMN ip_addr,
+    ADD COLUMN (
+        prefix VARBINARY(16) NOT NULL,
+        prefix_length TINYINT UNSIGNED NOT NULL,
+        prefix_max_length TINYINT UNSIGNED NOT NULL),
+    ADD CHECK (length(prefix) = 4 OR length(prefix) = 16),
+    ADD CHECK (prefix_length <= prefix_max_length),
+    ADD CHECK (prefix_max_length <= length(prefix) * 8),
+    ADD PRIMARY KEY (serial_num, asn, prefix, prefix_length, 
prefix_max_length);
+
+ALTER TABLE rtr_incremental
+    DROP PRIMARY KEY,
+    DROP COLUMN ip_addr,
+    ADD COLUMN (
+        prefix VARBINARY(16) NOT NULL,
+        prefix_length TINYINT UNSIGNED NOT NULL,
+        prefix_max_length TINYINT UNSIGNED NOT NULL),
+    ADD CHECK (length(prefix) = 4 OR length(prefix) = 16),
+    ADD CHECK (prefix_length <= prefix_max_length),
+    ADD CHECK (prefix_max_length <= length(prefix) * 8),
+    ADD PRIMARY KEY (serial_num, asn, prefix, prefix_length, 
prefix_max_length);
+EOF
+
+    log "Re-adding ROAs with new schema."
+    find "`config_get RPKICacheDir`" -type f -name \*.roa -print \
+        | rcli -l || fatal "Failed to re-add ROAs."
+
+    log "Re-initializing rpki-rtr data."
+    rpki-rtr-initialize || fatal "Could not re-initialize rpki-rtr."
+
+    # Don't run rpki-rtr-update here, because it's possible that the
+    # user has tweaked their local cache in some way that they're not
+    # ready to push out to routers yet. In the nominal case, our not
+    # running rpki-rtr-update here isn't a big deal because it will
+    # be run reasonably soon by cron, and the routers should be
+    # configured with multiple cache servers anyway.
+    add_msg "\
+The rpki-rtr data was cleared and re-initialized, but no updates were
+created. If you want to start sending data to routers again, run
+%s-rpki-rtr-update." \
+        "@PACKAGE_NAME@"
+
     return 0
 }
 
+upgrade_from_0_9 () {
+    upgrade_from_0_10
+    return $?
+}
+
 upgrade_from_0_8 () {
     echo "Attempting to create @pkgvarlibdir@."
     mkdir -p "@pkgvarlibdir@" && chmod 700 "@pkgvarlibdir@" \
@@ -136,6 +218,10 @@ case "$OLD_VERSION" in
         upgrade_from_0_9 || exit $?
         ;;
 
+    0.10)
+        upgrade_from_0_10 || exit $?
+        ;;
+
     "@PACKAGE_VERSION@")
         usage_fatal "Please specify the version you're upgrading from, not" \
                     "the version you're upgrading to."
diff --git a/lib/rpki/scmmain.h b/lib/rpki/scmmain.h
index 8ae143e..04ab33a 100644
--- a/lib/rpki/scmmain.h
+++ b/lib/rpki/scmmain.h
@@ -8,6 +8,31 @@
 
 #ifdef SCM_DEFINED_HERE
 
+/**
+ * @brief Column definitions to represent a prefix and maximum length.
+ *
+ *   - prefix: IPv4 or IPv6 prefix, network byte order, filled with 0s
+ *     to the full length for the address family. E.g., 1.2.3.0 would
+ *     be 0x01020300, and 123:4567:: would be
+ *     0x01234567000000000000000000000000
+ *   - prefix_length: Number of used bits in prefix.
+ *   - prefix_max_length: Maximum length of any sub-prefixes.
+ *
+ * @sa SCM_CHECKS_PREFIX_MAXLEN
+ */
+#define SCM_COLDEFS_PREFIX_MAXLEN \
+    "prefix VARBINARY(16) NOT NULL," \
+    "prefix_length TINYINT UNSIGNED NOT NULL," \
+    "prefix_max_length TINYINT UNSIGNED NOT NULL"
+
+/**
+ * @brief CHECKs for the columns in #SCM_COLDEFS_PREFIX_MAXLEN.
+ */
+#define SCM_CHECKS_PREFIX_MAXLEN \
+    "CHECK (length(prefix) = 4 OR length(prefix) = 16)," \
+    "CHECK (prefix_length <= prefix_max_length)," \
+    "CHECK (prefix_max_length <= length(prefix) * 8)"
+
 /*
  * Table definitions 
  */
@@ -96,8 +121,7 @@ static scmtab scmtabbuilder[] = {
       * Usage notes: the ski is the ski of the signing cert, and is thus
       * effectively the parent of this ROA. The asn is the AS number from the
       * ROA (there is only one now, not a list). The IP address information is 
-      * not stored here; it must be fetched from the file itself using the ROA 
-      * read code. local_id is as with certs and crls. 
+      * stored in rpki_roa_prefix below. local_id is as with certs and crls.
       */
      "rpki_roa",
      "ROA",
@@ -107,7 +131,6 @@ static scmtab scmtabbuilder[] = {
      "sig      VARCHAR(520) NOT NULL,"
      "sigval   INT UNSIGNED DEFAULT 0,"
      "hash     VARCHAR(256),"
-     "ip_addrs VARCHAR(32768) NOT NULL,"
      "asn      INT UNSIGNED NOT NULL,"
      "flags    INT UNSIGNED DEFAULT 0,"
      "local_id INT UNSIGNED NOT NULL UNIQUE,"
@@ -118,6 +141,18 @@ static scmtab scmtabbuilder[] = {
      "         KEY ski (ski)",
      NULL,
      0},
+    {
+     "rpki_roa_prefix",
+     "ROA_PREFIX",
+     "roa_local_id INT UNSIGNED NOT NULL,"
+     SCM_COLDEFS_PREFIX_MAXLEN ","
+     "KEY (roa_local_id, prefix),"
+     "FOREIGN KEY (roa_local_id) REFERENCES rpki_roa (local_id) "
+     "    ON DELETE CASCADE "
+     "    ON UPDATE CASCADE,"
+     SCM_CHECKS_PREFIX_MAXLEN,
+     NULL,
+     0},
     {                           /* RPKI_MANIFEST */
      "rpki_manifest",
      "MANIFEST",
@@ -207,8 +242,9 @@ static scmtab scmtabbuilder[] = {
      "RTR_FULL",
      "serial_num  INT UNSIGNED NOT NULL,"
      "asn         INT UNSIGNED NOT NULL,"
-     "ip_addr     VARCHAR(50) NOT NULL,"
-     "            PRIMARY KEY (serial_num, asn, ip_addr)",
+     SCM_COLDEFS_PREFIX_MAXLEN ","
+     "            PRIMARY KEY (serial_num, asn, prefix, prefix_length, 
prefix_max_length),"
+     SCM_CHECKS_PREFIX_MAXLEN,
      NULL,
      0},
     {                           /* RTR_INCREMENTAL */
@@ -223,12 +259,16 @@ static scmtab scmtabbuilder[] = {
                                                  * x */
      "is_announce BOOLEAN NOT NULL,"    /* announcement or withdrawal */
      "asn         INT UNSIGNED NOT NULL,"
-     "ip_addr     VARCHAR(50) NOT NULL,"
-     "            PRIMARY KEY (serial_num, asn, ip_addr)",
+     SCM_COLDEFS_PREFIX_MAXLEN ","
+     "            PRIMARY KEY (serial_num, asn, prefix, prefix_length, 
prefix_max_length),"
+     SCM_CHECKS_PREFIX_MAXLEN,
      NULL,
      0},
 };
 
+#undef SCM_COLDEFS_PREFIX_MAXLEN
+#undef SCM_CHECKS_PREFIX_MAXLEN
+
 #endif
 
 #endif
-- 
1.9.1


------------------------------------------------------------------------------
_______________________________________________
rpstir-devel mailing list
rpstir-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpstir-devel

Reply via email to