Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Add ecu_version_report counter for primary
Browse files Browse the repository at this point in the history
According to the standard of Uptane, add counter for
ECU version report. Currently, only added for primary.
It's name in the manifest is "report_counter", in the
payload of primary ecu version report.

Signed-off-by: cheng.xiang <ext-cheng.xiang@here.com>
  • Loading branch information
xcheng-here committed Nov 20, 2019
1 parent 95cf48e commit ab445d4
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 2 deletions.
9 changes: 9 additions & 0 deletions config/sql/migration/migrate.22.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Don't modify this! Create a new migration instead--see docs/schema-migrations.adoc
SAVEPOINT MIGRATION;

CREATE TABLE ecu_report_counter(ecu_serial TEXT NOT NULL PRIMARY KEY, counter INTEGER NOT NULL DEFAULT 0);

DELETE FROM version;
INSERT INTO version VALUES(22);

RELEASE MIGRATION;
9 changes: 9 additions & 0 deletions config/sql/rollback/rollback.22.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Don't modify this! Create a new migration instead--see docs/schema-migrations.adoc
SAVEPOINT ROLLBACK_MIGRATION;

DROP TABLE ecu_report_counter;

DELETE FROM version;
INSERT INTO version VALUES(21);

RELEASE ROLLBACK_MIGRATION;
3 changes: 2 additions & 1 deletion config/sql/schema.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CREATE TABLE version(version INTEGER);
INSERT INTO version(rowid,version) VALUES(1,21);
INSERT INTO version(rowid,version) VALUES(1,22);
CREATE TABLE device_info(unique_mark INTEGER PRIMARY KEY CHECK (unique_mark = 0), device_id TEXT, is_registered INTEGER NOT NULL DEFAULT 0 CHECK (is_registered IN (0,1)));
CREATE TABLE ecu_serials(id INTEGER PRIMARY KEY, serial TEXT UNIQUE, hardware_id TEXT NOT NULL, is_primary INTEGER NOT NULL DEFAULT 0 CHECK (is_primary IN (0,1)));
CREATE TABLE misconfigured_ecus(serial TEXT UNIQUE, hardware_id TEXT NOT NULL, state INTEGER NOT NULL CHECK (state IN (0,1)));
Expand All @@ -23,3 +23,4 @@ CREATE TABLE ecu_installation_results(ecu_serial TEXT NOT NULL PRIMARY KEY, succ
CREATE TABLE need_reboot(unique_mark INTEGER PRIMARY KEY CHECK (unique_mark = 0), flag INTEGER NOT NULL DEFAULT 0);
CREATE TABLE rollback_migrations(version_from INT PRIMARY KEY, migration TEXT NOT NULL);
CREATE TABLE delegations(meta BLOB NOT NULL, role_name TEXT NOT NULL, UNIQUE(role_name));
CREATE TABLE ecu_report_counter(ecu_serial TEXT NOT NULL PRIMARY KEY, counter INTEGER NOT NULL DEFAULT 0);
23 changes: 22 additions & 1 deletion src/libaktualizr/primary/initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,28 @@ InitRetCode Initializer::initEcuRegister() {
return InitRetCode::kOk;
}

bool Initializer::initEcuReportCounter() {
std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;

if (storage_->loadEcuReportCounter(&ecu_cnt)) {
return true;
}

EcuSerials ecu_serials;

if (!storage_->loadEcuSerials(&ecu_serials) || (ecu_serials.size() == 0)) {
return false;
}

storage_->saveEcuReportCounter(Uptane::EcuSerial(ecu_serials[0].first.ToString()), 0);

return true;
}
// Postcondition: "ECUs registered" flag set in the storage
Initializer::Initializer(
const ProvisionConfig& config_in, std::shared_ptr<INvStorage> storage_in,
std::shared_ptr<HttpInterface> http_client_in, KeyManager& keys_in,
const std::map<Uptane::EcuSerial, std::shared_ptr<Uptane::SecondaryInterface> >& secondary_info_in)
const std::map<Uptane::EcuSerial, std::shared_ptr<Uptane::SecondaryInterface>>& secondary_info_in)
: config_(config_in),
storage_(std::move(storage_in)),
http_client_(std::move(http_client_in)),
Expand Down Expand Up @@ -241,6 +258,10 @@ Initializer::Initializer(
LOG_ERROR << "ECU serial generation failed. Aborting initialization.";
return;
}
if (!initEcuReportCounter()) {
LOG_ERROR << "ECU report counter init failed. Aborting initialization.";
return;
}

ret_code = initEcuRegister();
// if ECUs with same ID have been registered to the server, we don't have a
Expand Down
1 change: 1 addition & 0 deletions src/libaktualizr/primary/initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Initializer {
void resetTlsCreds();
InitRetCode initEcuRegister();
bool loadSetTlsCreds(); // TODO -> metadownloader
bool initEcuReportCounter();
};

#endif // INITIALIZER_H_
7 changes: 7 additions & 0 deletions src/libaktualizr/primary/sotauptaneclient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ Json::Value SotaUptaneClient::AssembleManifest() {
Json::Value version_manifest;

Json::Value primary_ecu_version = package_manager_->getManifest(primary_ecu_serial);
std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
if (!storage->loadEcuReportCounter(&ecu_cnt) || (ecu_cnt.size() == 0)) {
LOG_ERROR << "No ECU version report counter, please check the database!";
} else {
primary_ecu_version["report_counter"] = std::to_string(ecu_cnt[0].second + 1);
storage->saveEcuReportCounter(ecu_cnt[0].first, ecu_cnt[0].second + 1);
}
version_manifest[primary_ecu_serial.ToString()] = uptane_manifest.signManifest(primary_ecu_version);

for (auto it = secondaries.begin(); it != secondaries.end(); it++) {
Expand Down
3 changes: 3 additions & 0 deletions src/libaktualizr/storage/invstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ class INvStorage {
std::string* correlation_id) = 0;
virtual void clearInstallationResults() = 0;

virtual void saveEcuReportCounter(const Uptane::EcuSerial& ecu_serial, const int64_t counter) = 0;
virtual bool loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) = 0;

virtual boost::optional<std::pair<size_t, std::string>> checkTargetFile(const Uptane::Target& target) const = 0;

// Incremental file API
Expand Down
51 changes: 51 additions & 0 deletions src/libaktualizr/storage/sqlstorage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,57 @@ bool SQLStorage::loadDeviceInstallationResult(data::InstallationResult* result,
return true;
}

void SQLStorage::saveEcuReportCounter(const Uptane::EcuSerial& ecu_serial, const int64_t counter) {
SQLite3Guard db = dbConnection();

auto statement = db.prepareStatement<std::string, int64_t>(
"INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
"(?,?);",
ecu_serial.ToString(), counter);
if (statement.step() != SQLITE_DONE) {
LOG_ERROR << "Can't set ecu counter: " << db.errmsg();
return;
}
}

bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) {
SQLite3Guard db = dbConnection();

std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;

// keep the same order as in ecu_serials (start with primary)
auto statement = db.prepareStatement(
"SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecu_serials ON "
"ecu_serials.serial = ecu_serial ORDER BY ecu_serials.id;");
int statement_result = statement.step();
if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
LOG_ERROR << "Can't get ecu_report_counter: " << db.errmsg();
return false;
}

if (statement_result == SQLITE_DONE) {
// if there are no any record in the DB
return false;
}

for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
try {
std::string ecu_serial = statement.get_result_col_str(0).value();
int64_t counter = statement.get_result_col_int(1);

ecu_cnt.emplace_back(Uptane::EcuSerial(ecu_serial), counter);
} catch (const boost::bad_optional_access&) {
return false;
}
}

if (results != nullptr) {
*results = std::move(ecu_cnt);
}

return true;
}

void SQLStorage::clearInstallationResults() {
SQLite3Guard db = dbConnection();
if (!db.beginTransaction()) {
Expand Down
2 changes: 2 additions & 0 deletions src/libaktualizr/storage/sqlstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class SQLStorage : public SQLStorageBase, public INvStorage {
const std::string& correlation_id) override;
bool loadDeviceInstallationResult(data::InstallationResult* result, std::string* raw_report,
std::string* correlation_id) override;
void saveEcuReportCounter(const Uptane::EcuSerial& ecu_serial, const int64_t counter) override;
bool loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) override;
void clearInstallationResults() override;

std::unique_ptr<StorageTargetWHandle> allocateTargetFile(bool from_director, const Uptane::Target& target) override;
Expand Down
7 changes: 7 additions & 0 deletions src/libaktualizr/uptane/uptane_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ TEST(Uptane, AssembleManifestGood) {
// Manifest should not have an installation result yet.
EXPECT_FALSE(manifest["testecuserial"]["signed"].isMember("custom"));
EXPECT_FALSE(manifest["secondary_ecu_serial"]["signed"].isMember("custom"));

std::string counter_str = manifest["testecuserial"]["signed"]["report_counter"].asString();
int64_t primary_ecu_report_counter = std::stoll(counter_str);
Json::Value manifest2 = sota_client->AssembleManifest()["ecu_version_manifests"];
std::string counter_str2 = manifest2["testecuserial"]["signed"]["report_counter"].asString();
int64_t primary_ecu_report_counter2 = std::stoll(counter_str2);
EXPECT_EQ(primary_ecu_report_counter2, primary_ecu_report_counter + 1);
}

/* Bad signatures are ignored when assembling the manifest. */
Expand Down

0 comments on commit ab445d4

Please sign in to comment.