When I had playing with bluhm@'s ipsec(4) diffs I found my system always manages to complete rekeying and I have no TDB's with hardlimit excess. It seems I'm not the only such person and other testers also don't have panics Hrvoje Popovski had.
I want to count the TDBs with hardlimit excess as the new `ipsec_exctdb' ipsec(4) counter and export this statistics to userland. So if the tester person will expose something like below, we could say he didn't reach the fragile tdb_delete() paths. [otto@obsd-test ~]$ netstat -s -p ipsec ipsec: 44684 input IPsec packets 44603 output IPsec packets 7505232 input bytes 7490792 output bytes 5405234 input bytes, decompressed 5706290 output bytes, uncompressed 1 packet dropped on input 0 packets dropped on output 0 packets that failed crypto processing 0 packets for which no XFORM was set in TDB received 0 packets for which no TDB was found 0 TDBs with hard limit excess Also I found the `ipsec_notdb' counter description in header doesn't math to netstat(1) description. We never count `ipsec_notdb' and the netstat(1) description looks more appropriate so I used it to avoid confusion with the new counter added. ok? Index: sys/netinet/ip_ah.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ah.c,v retrieving revision 1.166 diff -u -p -r1.166 ip_ah.c --- sys/netinet/ip_ah.c 11 Nov 2021 18:08:18 -0000 1.166 +++ sys/netinet/ip_ah.c 20 Nov 2021 23:32:57 -0000 @@ -616,6 +616,7 @@ ah_input(struct mbuf **mp, struct tdb *t tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); + ipsecstat_inc(ipsec_exctdb); goto drop; } @@ -955,6 +956,7 @@ ah_output(struct mbuf *m, struct tdb *td tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); + ipsecstat_inc(ipsec_exctdb); error = EINVAL; goto drop; } Index: sys/netinet/ip_esp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_esp.c,v retrieving revision 1.187 diff -u -p -r1.187 ip_esp.c --- sys/netinet/ip_esp.c 11 Nov 2021 18:08:18 -0000 1.187 +++ sys/netinet/ip_esp.c 20 Nov 2021 23:32:57 -0000 @@ -428,6 +428,7 @@ esp_input(struct mbuf **mp, struct tdb * (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); + ipsecstat_inc(ipsec_exctdb); goto drop; } @@ -784,6 +785,7 @@ esp_output(struct mbuf *m, struct tdb *t tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); + ipsecstat_inc(ipsec_exctdb); error = EINVAL; goto drop; } Index: sys/netinet/ip_ipcomp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ipcomp.c,v retrieving revision 1.87 diff -u -p -r1.87 ip_ipcomp.c --- sys/netinet/ip_ipcomp.c 11 Nov 2021 18:08:18 -0000 1.87 +++ sys/netinet/ip_ipcomp.c 20 Nov 2021 23:32:57 -0000 @@ -201,6 +201,7 @@ ipcomp_input(struct mbuf **mp, struct td (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); + ipsecstat_inc(ipsec_exctdb); goto drop; } /* Notify on soft expiration */ @@ -388,6 +389,7 @@ ipcomp_output(struct mbuf *m, struct tdb (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); + ipsecstat_inc(ipsec_exctdb); error = EINVAL; goto drop; } Index: sys/netinet/ip_ipsp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v retrieving revision 1.251 diff -u -p -r1.251 ip_ipsp.c --- sys/netinet/ip_ipsp.c 18 Nov 2021 11:04:10 -0000 1.251 +++ sys/netinet/ip_ipsp.c 20 Nov 2021 23:32:57 -0000 @@ -652,8 +652,10 @@ tdb_timeout(void *v) NET_LOCK(); if (tdb->tdb_flags & TDBF_TIMER) { /* If it's an "invalid" TDB do a silent expiration. */ - if (!(tdb->tdb_flags & TDBF_INVALID)) + if (!(tdb->tdb_flags & TDBF_INVALID)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); + ipsecstat_inc(ipsec_exctdb); + } tdb_delete(tdb); } NET_UNLOCK(); @@ -667,8 +669,10 @@ tdb_firstuse(void *v) NET_LOCK(); if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) { /* If the TDB hasn't been used, don't renew it. */ - if (tdb->tdb_first_use != 0) + if (tdb->tdb_first_use != 0) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); + ipsecstat_inc(ipsec_exctdb); + } tdb_delete(tdb); } NET_UNLOCK(); Index: sys/netinet/ip_ipsp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v retrieving revision 1.220 diff -u -p -r1.220 ip_ipsp.h --- sys/netinet/ip_ipsp.h 16 Nov 2021 13:53:14 -0000 1.220 +++ sys/netinet/ip_ipsp.h 20 Nov 2021 23:32:57 -0000 @@ -131,8 +131,9 @@ struct ipsecstat { uint64_t ipsec_idrops; /* Dropped on input */ uint64_t ipsec_odrops; /* Dropped on output */ uint64_t ipsec_crypto; /* Crypto processing failure */ - uint64_t ipsec_notdb; /* Expired while in crypto */ + uint64_t ipsec_notdb; /* No TDB was found */ uint64_t ipsec_noxform; /* Crypto error */ + uint64_t ipsec_exctdb; /* TDBs with hardlimit excess */ }; struct tdb_data { @@ -168,6 +169,7 @@ enum ipsec_counters { ipsec_crypto, ipsec_notdb, ipsec_noxform, + ipsec_exctdb, ipsec_ncounters }; Index: usr.bin/netstat/inet.c =================================================================== RCS file: /cvs/src/usr.bin/netstat/inet.c,v retrieving revision 1.171 diff -u -p -r1.171 inet.c --- usr.bin/netstat/inet.c 26 Jan 2021 18:22:35 -0000 1.171 +++ usr.bin/netstat/inet.c 20 Nov 2021 23:32:59 -0000 @@ -1046,6 +1046,7 @@ ipsec_stats(char *name) p(ipsec_crypto, "\t%llu packet%s that failed crypto processing\n"); p(ipsec_noxform, "\t%llu packet%s for which no XFORM was set in TDB received\n"); p(ipsec_notdb, "\t%llu packet%s for which no TDB was found\n"); + p(ipsec_exctdb, "\t%llu TDB%s with hardlimit excess\n"); #undef p }