mesh: Improve Network Message Cache behavior

The implementation of the Network Message Cache has so far been
suboptimal, since it has treated the same packet with different TTL
values as different packets. Since one of the purposes of this cache
is to prevent unnecessary relaying, it's important that we don't let
the TTL value influence the "hash" that's used for matching messages.

This patch changes the hash to consist of most of the IV Index (three
least significant bytes of it), the sequence number and the source
address, which should give fairly optimal matching behavior.

X-Original-Commit: 311263736dbe417f254413ab63dcd3f99aca32a8
This commit is contained in:
Michał Narajowski
2017-11-09 11:58:33 +01:00
parent 81368cdefc
commit 15597be926
2 changed files with 16 additions and 31 deletions
+16 -30
View File
@@ -99,32 +99,23 @@ static bool check_dup(struct os_mbuf *data)
return false;
}
static u64_t msg_hash(struct os_mbuf *pdu)
static u64_t msg_hash(struct bt_mesh_net_rx *rx, struct os_mbuf *pdu)
{
u8_t *tpdu_last;
u64_t hash;
u32_t hash1, hash2;
/* Last byte of TransportPDU */
tpdu_last = net_buf_simple_tail(pdu) - (CTL(pdu->om_data) ? 8 : 4) - 1;
/* Three least significant bytes of IVI + first byte of SEQ */
hash1 = (BT_MESH_NET_IVI_RX(rx) << 8) | pdu->om_data[2];
((u8_t *)(&hash))[0] = pdu->om_data[0];
((u8_t *)(&hash))[1] = (pdu->om_data[1] & 0xc0);
((u8_t *)(&hash))[2] = *tpdu_last;
memcpy(&((u8_t *)&hash)[3], &pdu->om_data[2], 5);
/* Two last bytes of SEQ + SRC */
memcpy(&hash2, &pdu->om_data[3], 4);
BT_DBG("hash=%llx", hash)
return hash;
return (u64_t)hash1 << 32 | (u64_t)hash2;
}
static void msg_cache_add(u64_t new_hash)
{
msg_cache[msg_cache_next++] = new_hash;
msg_cache_next %= ARRAY_SIZE(msg_cache);
}
static bool msg_is_known(u64_t hash)
static bool msg_cache_match(struct bt_mesh_net_rx *rx,
struct os_mbuf *pdu)
{
u64_t hash = msg_hash(rx, pdu);
u16_t i;
for (i = 0; i < ARRAY_SIZE(msg_cache); i++) {
@@ -133,6 +124,10 @@ static bool msg_is_known(u64_t hash)
}
}
/* Add to the cache */
msg_cache[msg_cache_next++] = hash;
msg_cache_next %= ARRAY_SIZE(msg_cache);
return false;
}
@@ -944,8 +939,8 @@ static int net_decrypt(struct bt_mesh_subnet *sub, u8_t idx, const u8_t *data,
return -ENOENT;
}
if (msg_is_known(rx->hash)) {
BT_DBG("Message is already in cache; hash=%llx", rx->hash);
if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) {
BT_WARN("Duplicate found in Network Message Cache");
return -EALREADY;
}
@@ -1132,10 +1127,6 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
rx->net_if = net_if;
if (net_if == BT_MESH_NET_IF_ADV) {
rx->hash = msg_hash(data);
}
if (!net_find_and_decrypt(data->om_data, data->om_len, rx, buf)) {
BT_DBG("Unable to find matching net for packet");
return -ENOENT;
@@ -1183,11 +1174,6 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
return -EBADMSG;
}
if (net_if == BT_MESH_NET_IF_ADV) {
BT_DBG("Add message to cache; hash=%llx", rx->hash);
msg_cache_add(rx->hash);
}
BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->dst,
rx->ctx.recv_ttl);
BT_DBG("PDU: %s", bt_hex(buf->om_data, buf->om_len));
-1
View File
@@ -216,7 +216,6 @@ struct bt_mesh_net_rx
{
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx ctx;
u64_t hash; /* Hash for the relay cache */
u32_t seq; /* Sequence Number */
u16_t dst; /* Destination address */
u8_t old_iv :1, /* iv_index - 1 was used */