Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions nimble/host/include/host/ble_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ struct ble_store_value_sec {
/** Peer address for which the security material is stored. */
ble_addr_t peer_addr;

/**
* Optional recency counter for LRU bond eviction. Maintained by the store
* implementation if ble_store_util_status_lru is used. A lower value means
* the peer was used less recently.
*/
uint16_t bond_count;

/** Encryption key size. */
uint8_t key_size;
/** Encrypted Diversifier used for encryption key generation. */
Expand Down Expand Up @@ -744,6 +751,28 @@ int ble_store_util_count(int type, int *out_count);
*/
int ble_store_util_status_rr(struct ble_store_status_event *event, void *arg);

/**
* @brief LRU status callback for handling store status events.
*
* This function handles store status events when there is insufficient storage
* capacity for new records. It resolves overflow by deleting the
* least-recently-used bond and proceeds with the persist operation.
*
* Recency is determined from ble_store_value_sec.bond_count when the store
* implementation maintains it. Prefer this over ble_store_util_status_rr when
* recently used bonds should be retained.
*
* Register from the application with:
* ble_hs_cfg.store_status_cb = ble_store_util_status_lru;
*
* @param event A pointer to the store status event.
* @param arg A pointer to additional user-defined arguments.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_util_status_lru(struct ble_store_status_event *event, void *arg);

/** @} */

#ifdef __cplusplus
Expand Down
109 changes: 109 additions & 0 deletions nimble/host/src/ble_store_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,112 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
return BLE_HS_EUNKNOWN;
}
}

struct ble_store_util_lru_peer {
ble_addr_t peer_addr;
uint16_t bond_count;
int found;
const ble_addr_t *except;
};

static int
ble_store_util_iter_lru_peer(int obj_type, union ble_store_value *val, void *arg)
{
struct ble_store_util_lru_peer *lru;

BLE_HS_DBG_ASSERT(obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC);

lru = arg;

if (lru->except != NULL && ble_addr_cmp(lru->except, &val->sec.peer_addr) == 0) {
return 0;
}

if (!lru->found || val->sec.bond_count < lru->bond_count) {
lru->peer_addr = val->sec.peer_addr;
lru->bond_count = val->sec.bond_count;
lru->found = 1;
}

return 0;
}

static int
ble_store_util_find_lru_peer(ble_addr_t *out_peer_addr, const ble_addr_t *except)
{
struct ble_store_util_lru_peer lru = {
.found = 0,
.except = except,
};
int rc;

rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_OUR_SEC,
ble_store_util_iter_lru_peer, &lru);
if (rc != 0) {
return rc;
}

if (!lru.found) {
return BLE_HS_ENOENT;
}

*out_peer_addr = lru.peer_addr;
return 0;
}

static int
ble_store_util_unpair_lru_peer(void)
{
ble_addr_t peer_addr;
int rc;

rc = ble_store_util_find_lru_peer(&peer_addr, NULL);
if (rc != 0) {
return rc;
}

return ble_gap_unpair(&peer_addr);
}

static int
ble_store_util_unpair_lru_except(const ble_addr_t *except)
{
ble_addr_t peer_addr;
int rc;

rc = ble_store_util_find_lru_peer(&peer_addr, except);
if (rc != 0) {
return rc;
}

return ble_gap_unpair(&peer_addr);
}

int
ble_store_util_status_lru(struct ble_store_status_event *event, void *arg)
{
switch (event->event_code) {
case BLE_STORE_EVENT_OVERFLOW:
switch (event->overflow.obj_type) {
case BLE_STORE_OBJ_TYPE_OUR_SEC:
case BLE_STORE_OBJ_TYPE_PEER_SEC:
return ble_store_util_unpair_lru_peer();
case BLE_STORE_OBJ_TYPE_CCCD:
/* Try unpairing LRU peer except current peer */
return ble_store_util_unpair_lru_except(
&event->overflow.value->cccd.peer_addr);

default:
return BLE_HS_EUNKNOWN;
}

case BLE_STORE_EVENT_FULL:
/* Just proceed with the operation. If it results in an overflow,
* we'll delete a record when the overflow occurs.
*/
return 0;

default:
return BLE_HS_EUNKNOWN;
}
}
Loading