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