From: David Mandelberg <dmand...@bbn.com>

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 | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/rpki/scmmain.h  |  52 +++++++++++++++++++++++---
 2 files changed, 151 insertions(+), 6 deletions(-)

diff --git a/bin/rpki/upgrade.in b/bin/rpki/upgrade.in
index 1ecfb57..7334e6f 100644
--- a/bin/rpki/upgrade.in
+++ b/bin/rpki/upgrade.in
@@ -52,10 +52,109 @@ show_msgs () {
 }
 
 
-upgrade_from_0_9 () {
+upgrade_from_0_10 () {
+    echo "Clearing rpki-rtr data before altering schema."
+    rpki-rtr-clear -f || \
+    {
+        error "Could not clear rpki-rtr data."
+        return 1
+    }
+
+    echo "Removing all ROAs from the database before altering schema."
+    find "`config_get RPKICacheDir`" -type f -name \*.roa \
+        -exec rcli -d "{}" ";" || \
+    {
+        add_msg "\
+Potentially failed to remove all ROA files before upgrading the
+database schema. This is probably not a problem."
+    }
+
+    echo "Updating the database schema."
+    {
+        echo "ALTER TABLE rpki_roa DROP COLUMN ip_addrs;"
+
+        echo \
+            "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)" \
+            ");"
+
+        # Note that this does not add SCM_CHECKS_PREFIX_MAXLEN because
+        # MySQL's ALTER TABLE statement doesn't provide the syntax to
+        # add a CHECK. MySQL ignores CHECKs completely though, so this
+        # doesn't really matter.
+        echo \
+            "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 PRIMARY KEY (serial_num, asn, prefix, prefix_length, 
prefix_max_length)" \
+            ";"
+
+        # See the above note about CHECKs.
+        echo \
+            "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 PRIMARY KEY (serial_num, asn, prefix, prefix_length, 
prefix_max_length)" \
+            ";"
+    } | mysql_cmd || \
+    {
+        error "Could not update the database schema."
+        return 1
+    }
+
+    echo "Re-adding ROAs with new schema."
+    find "`config_get RPKICacheDir`" -type f -name \*.roa -print \
+        | rcli -l || \
+    {
+        error "Failed to re-add ROAs."
+        return 1
+    }
+
+    echo "Re-initializing rpki-rtr data."
+    rpki-rtr-initialize || \
+    {
+        error "Could not re-initialize rpki-rtr."
+        return 1
+    }
+
+    # 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 +235,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..289e7bb 100644
--- a/lib/rpki/scmmain.h
+++ b/lib/rpki/scmmain.h
@@ -8,6 +8,32 @@
 
 #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 
  */
@@ -107,7 +133,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 +143,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 +244,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 +261,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


------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
rpstir-devel mailing list
rpstir-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpstir-devel

Reply via email to