From: Theo Buehler Subject: rpki-client: stats for non-functional CAs To: tech@openbsd.org Date: Thu, 3 Apr 2025 11:09:01 +0200 This adds a simple counter for the non-functional CAs to the summary, the ometrics and the json output. It tracks the number of certs per tal in the nca tree. It appears next to wherever the invalid CAs are listed (certs_fail). Index: cert.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v diff -u -p -r1.157 cert.c --- cert.c 27 Mar 2025 05:03:09 -0000 1.157 +++ cert.c 3 Apr 2025 07:43:04 -0000 @@ -1395,7 +1395,7 @@ RB_GENERATE(brk_tree, brk, entry, brkcmp * Add each CA cert into the non-functional CA tree. */ void -cert_insert_nca(struct nca_tree *tree, const struct cert *cert) +cert_insert_nca(struct nca_tree *tree, const struct cert *cert, struct repo *rp) { struct nonfunc_ca *nca; @@ -1414,15 +1414,17 @@ cert_insert_nca(struct nca_tree *tree, c if (RB_INSERT(nca_tree, tree, nca) != NULL) errx(1, "non-functional CA tree corrupted"); + repo_stat_inc(rp, nca->talid, RTYPE_CER, STYPE_NONFUNC); } void -cert_remove_nca(struct nca_tree *tree, int cid) +cert_remove_nca(struct nca_tree *tree, int cid, struct repo *rp) { struct nonfunc_ca *found, needle = { .certid = cid }; if ((found = RB_FIND(nca_tree, tree, &needle)) != NULL) { RB_REMOVE(nca_tree, tree, found); + repo_stat_inc(rp, found->talid, RTYPE_CER, STYPE_FUNC); free(found->location); free(found->carepo); free(found->mfturi); Index: extern.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v diff -u -p -r1.238 extern.h --- extern.h 27 Mar 2025 05:03:09 -0000 1.238 +++ extern.h 3 Apr 2025 07:40:19 -0000 @@ -610,6 +610,8 @@ enum stype { STYPE_PROVIDERS, STYPE_OVERFLOW, STYPE_SEQNUM_GAP, + STYPE_FUNC, + STYPE_NONFUNC, }; struct repo; @@ -623,6 +625,7 @@ RB_HEAD(filepath_tree, filepath); struct repotalstats { uint32_t certs; /* certificates */ uint32_t certs_fail; /* invalid certificate */ + uint32_t certs_nonfunc; /* non-functional CA certificates */ uint32_t mfts; /* total number of manifests */ uint32_t mfts_gap; /* manifests with sequence gaps */ uint32_t mfts_fail; /* failing syntactic parse */ @@ -709,8 +712,9 @@ struct cert *ta_parse(const char *, stru size_t); struct cert *cert_read(struct ibuf *); void cert_insert_brks(struct brk_tree *, struct cert *); -void cert_insert_nca(struct nca_tree *, const struct cert *); -void cert_remove_nca(struct nca_tree *, int); +void cert_insert_nca(struct nca_tree *, const struct cert *, + struct repo *); +void cert_remove_nca(struct nca_tree *, int, struct repo *); enum rtype rtype_from_file_extension(const char *); void mft_buffer(struct ibuf *, const struct mft *); Index: main.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v diff -u -p -r1.280 main.c --- main.c 27 Mar 2025 05:03:09 -0000 1.280 +++ main.c 3 Apr 2025 07:39:41 -0000 @@ -549,7 +549,7 @@ queue_add_from_cert(const struct cert *c err(1, NULL); } - cert_insert_nca(ncas, cert); + cert_insert_nca(ncas, cert, repo); entityq_add(npath, nfile, RTYPE_MFT, DIR_UNKNOWN, repo, NULL, 0, cert->talid, cert->certid, NULL); } @@ -642,7 +642,7 @@ entity_process(struct ibuf *b, struct st if (mft->seqnum_gap) repo_stat_inc(rp, talid, type, STYPE_SEQNUM_GAP); queue_add_from_mft(mft); - cert_remove_nca(ncatree, mft->certid); + cert_remove_nca(ncatree, mft->certid, rp); mft_free(mft); break; case RTYPE_CRL: @@ -770,6 +770,7 @@ sum_stats(const struct repo *rp, const s out->mfts_gap += in->mfts_gap; out->certs += in->certs; out->certs_fail += in->certs_fail; + out->certs_nonfunc += in->certs_nonfunc; out->roas += in->roas; out->roas_fail += in->roas_fail; out->roas_invalid += in->roas_invalid; @@ -1523,8 +1524,9 @@ main(int argc, char *argv[]) stats.repo_tal_stats.spls_invalid); } printf("BGPsec Router Certificates: %u\n", stats.repo_tal_stats.brks); - printf("Certificates: %u (%u invalid)\n", - stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail); + printf("Certificates: %u (%u invalid, %u non-functional)\n", + stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail, + stats.repo_tal_stats.certs_nonfunc); printf("Trust Anchor Locators: %u (%u invalid)\n", stats.tals, talsz - stats.tals); printf("Manifests: %u (%u failed parse, %u seqnum gaps)\n", Index: output-json.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/output-json.c,v diff -u -p -r1.52 output-json.c --- output-json.c 27 Mar 2025 05:03:09 -0000 1.52 +++ output-json.c 3 Apr 2025 07:38:55 -0000 @@ -58,6 +58,7 @@ outputheader_json(struct stats *st) json_do_int("bgpsec_pubkeys", st->repo_tal_stats.brks); json_do_int("certificates", st->repo_tal_stats.certs); json_do_int("invalidcertificates", st->repo_tal_stats.certs_fail); + json_do_int("nonfunctionalcas", st->repo_tal_stats.certs_nonfunc); json_do_int("taks", st->repo_tal_stats.taks); json_do_int("tals", st->tals); json_do_int("invalidtals", talsz - st->tals); Index: output-ometric.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/output-ometric.c,v diff -u -p -r1.13 output-ometric.c --- output-ometric.c 27 Mar 2025 05:03:09 -0000 1.13 +++ output-ometric.c 3 Apr 2025 07:41:00 -0000 @@ -42,6 +42,8 @@ set_common_stats(const struct repotalsta OKV("type", "state"), OKV("cert", "valid"), ol); ometric_set_int_with_labels(metric, in->certs_fail, OKV("type", "state"), OKV("cert", "failed parse"), ol); + ometric_set_int_with_labels(metric, in->certs_nonfunc, + OKV("type", "state"), OKV("cert", "non-functional"), ol); ometric_set_int_with_labels(metric, in->mfts, OKV("type", "state"), OKV("manifest", "valid"), ol); Index: output.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/output.c,v diff -u -p -r1.39 output.c --- output.c 27 Mar 2025 05:03:09 -0000 1.39 +++ output.c 3 Apr 2025 08:10:26 -0000 @@ -259,12 +259,13 @@ outputheader(FILE *out, struct stats *st "# Processing time %lld seconds (%llds user, %llds system)\n" "# Route Origin Authorizations: %u (%u failed parse, %u invalid)\n" "# BGPsec Router Certificates: %u\n" - "# Certificates: %u (%u invalid)\n", + "# Certificates: %u (%u invalid, %u non-functional)\n", hn, tbuf, (long long)st->elapsed_time.tv_sec, (long long)st->user_time.tv_sec, (long long)st->system_time.tv_sec, st->repo_tal_stats.roas, st->repo_tal_stats.roas_fail, st->repo_tal_stats.roas_invalid, st->repo_tal_stats.brks, - st->repo_tal_stats.certs, st->repo_tal_stats.certs_fail) < 0) + st->repo_tal_stats.certs, st->repo_tal_stats.certs_fail, + st->repo_tal_stats.certs_nonfunc) < 0) return -1; if (fprintf(out, Index: repo.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v diff -u -p -r1.74 repo.c --- repo.c 31 Mar 2025 08:59:02 -0000 1.74 +++ repo.c 3 Apr 2025 07:26:45 -0000 @@ -1515,6 +1515,10 @@ repo_stat_inc(struct repo *rp, int talid rp->stats[talid].certs++; if (subtype == STYPE_FAIL) rp->stats[talid].certs_fail++; + if (subtype == STYPE_NONFUNC) + rp->stats[talid].certs_nonfunc++; + if (subtype == STYPE_FUNC) + rp->stats[talid].certs_nonfunc--; if (subtype == STYPE_BGPSEC) { rp->stats[talid].certs--; rp->stats[talid].brks++;