All of lore.kernel.org
 help / color / mirror / Atom feed
From: Inga Stotland <inga.stotland@intel.com>
To: linux-bluetooth@vger.kernel.org
Cc: brian.gix@intel.com, Inga Stotland <inga.stotland@intel.com>
Subject: [PATCH BlueZ 04/20] tools/mesh-cfgclient: Keep track of updated keys
Date: Wed, 22 Sep 2021 20:25:47 -0700	[thread overview]
Message-ID: <20210923032603.50536-5-inga.stotland@intel.com> (raw)
In-Reply-To: <20210923032603.50536-1-inga.stotland@intel.com>

---
 tools/mesh/cfgcli.c  |  33 ++++----
 tools/mesh/mesh-db.c | 151 ++++++++++++++++++++++++++++++-----
 tools/mesh/mesh-db.h |   2 +
 tools/mesh/remote.c  | 182 +++++++++++++++++++++++++++++++++----------
 tools/mesh/remote.h  |   9 ++-
 5 files changed, 299 insertions(+), 78 deletions(-)

diff --git a/tools/mesh/cfgcli.c b/tools/mesh/cfgcli.c
index d8eee4edc..485d13b5a 100644
--- a/tools/mesh/cfgcli.c
+++ b/tools/mesh/cfgcli.c
@@ -447,13 +447,12 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
 		if (!cmd)
 			break;
 
-		if (cmd->opcode == OP_APPKEY_ADD) {
-			if (remote_add_app_key(src, app_idx))
-				mesh_db_node_app_key_add(src, app_idx);
-		} else if (cmd->opcode == OP_APPKEY_DELETE) {
-			if (remote_del_app_key(src, app_idx))
-				mesh_db_node_app_key_del(src, app_idx);
-		}
+		if (cmd->opcode == OP_APPKEY_ADD)
+			remote_add_app_key(src, app_idx, true);
+		else if (cmd->opcode == OP_APPKEY_DELETE)
+			remote_del_app_key(src, app_idx);
+		else if (cmd->opcode == OP_APPKEY_UPDATE)
+			remote_update_app_key(src, app_idx, true, true);
 
 		break;
 
@@ -492,13 +491,12 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
 		if (!cmd)
 			break;
 
-		if (cmd->opcode == OP_NETKEY_ADD) {
-			if (remote_add_net_key(src, net_idx))
-				mesh_db_node_net_key_add(src, net_idx);
-		} else if (cmd->opcode == OP_NETKEY_DELETE) {
-			if (remote_del_net_key(src, net_idx))
-				mesh_db_node_net_key_del(src, net_idx);
-		}
+		if (cmd->opcode == OP_NETKEY_ADD)
+			remote_add_net_key(src, net_idx, true);
+		else if (cmd->opcode == OP_NETKEY_DELETE)
+			remote_del_net_key(src, net_idx);
+		else if (cmd->opcode == OP_NETKEY_UPDATE)
+			remote_update_net_key(src, net_idx, true, true);
 
 		break;
 
@@ -534,6 +532,13 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
 
 		bt_shell_printf("\tNetKey %u (0x%3.3x)\n", net_idx, net_idx);
 		bt_shell_printf("\tKR Phase %2.2x\n", data[3]);
+
+		if (data[0] != MESH_STATUS_SUCCESS)
+			return true;
+
+		if (data[3] == KEY_REFRESH_PHASE_NONE)
+			remote_finish_key_refresh(src, net_idx);
+
 		break;
 
 	case OP_MODEL_APP_STATUS:
diff --git a/tools/mesh/mesh-db.c b/tools/mesh/mesh-db.c
index 5b3c4b2f7..a57a5d547 100644
--- a/tools/mesh/mesh-db.c
+++ b/tools/mesh/mesh-db.c
@@ -200,6 +200,38 @@ static bool write_int(json_object *jobj, const char *keyword, int val)
 	return true;
 }
 
+static bool get_bool(json_object *jobj, const char *keyword, bool *value)
+{
+	json_object *jvalue;
+
+	if (!json_object_object_get_ex(jobj, keyword, &jvalue))
+		return false;
+
+	if (json_object_get_type(jvalue) != json_type_boolean) {
+		l_error("Error: %s should contain a boolean value\n",
+								keyword);
+		return false;
+	}
+
+	*value = json_object_get_boolean(jvalue);
+
+	return true;
+}
+
+static bool write_bool(json_object *jobj, const char *keyword, bool val)
+{
+	json_object *jval;
+
+	json_object_object_del(jobj, keyword);
+
+	jval = json_object_new_boolean(val);
+	if (!jval)
+		return false;
+
+	json_object_object_add(jobj, keyword, jval);
+	return true;
+}
+
 static json_object *get_key_object(json_object *jarray, uint16_t idx)
 {
 	int i, sz = json_object_array_length(jarray);
@@ -347,6 +379,20 @@ static uint16_t node_parse_key(json_object *jarray, int i)
 	return (uint16_t)idx;
 }
 
+static bool node_check_key_updated(json_object *jarray, int i, bool *updated)
+{
+	json_object *jkey;
+
+	jkey = json_object_array_get_idx(jarray, i);
+	if (!jkey)
+		return false;
+
+	if (!get_bool(jkey, "updated", updated))
+		return false;
+
+	return true;
+}
+
 static int compare_group_addr(const void *a, const void *b, void *user_data)
 {
 	const struct mesh_group *grp0 = a;
@@ -483,10 +529,17 @@ static void load_remotes(json_object *jcfg)
 		remote_add_node((const uint8_t *)uuid, unicast, ele_cnt,
 								key_idx);
 		for (j = 1; j < key_cnt; j++) {
+			bool updated = false;
+
 			key_idx = node_parse_key(jarray, j);
 
-			if (key_idx != KEY_IDX_INVALID)
-				remote_add_net_key(unicast, key_idx);
+			if (key_idx == KEY_IDX_INVALID)
+				continue;
+
+			remote_add_net_key(unicast, key_idx, false);
+
+			node_check_key_updated(jarray, j, &updated);
+			remote_update_net_key(unicast, key_idx, updated, false);
 		}
 
 		json_object_object_get_ex(jnode, "appKeys", &jarray);
@@ -496,10 +549,17 @@ static void load_remotes(json_object *jcfg)
 		key_cnt = json_object_array_length(jarray);
 
 		for (j = 0; j < key_cnt; j++) {
+			bool updated = false;
+
 			key_idx = node_parse_key(jarray, j);
 
-			if (key_idx != KEY_IDX_INVALID)
-				remote_add_app_key(unicast, key_idx);
+			if (key_idx == KEY_IDX_INVALID)
+				continue;
+
+			remote_add_app_key(unicast, key_idx, false);
+
+			node_check_key_updated(jarray, j, &updated);
+			remote_update_app_key(unicast, key_idx, updated, false);
 		}
 
 		load_composition(jnode, unicast);
@@ -554,28 +614,19 @@ static bool add_node_key(json_object *jobj, const char *desc, uint16_t idx)
 
 	jkey = json_object_new_object();
 
-	if (!write_int(jkey, "index", (int)idx)) {
-		json_object_put(jkey);
-		return false;
-	}
+	if (!write_int(jkey, "index", (int)idx))
+		goto fail;
+
+	if (!write_bool(jkey, "updated", false))
+		goto fail;
 
 	json_object_array_add(jarray, jkey);
 
 	return save_config();
-}
-
-bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx)
-{
-	json_object *jnode;
-
-	if (!cfg || !cfg->jcfg)
-		return false;
 
-	jnode = get_node_by_unicast(unicast);
-	if (!jnode)
-		return false;
-
-	return add_node_key(jnode, "netKeys", idx);
+fail:
+	json_object_put(jkey);
+	return false;
 }
 
 bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl)
@@ -628,6 +679,20 @@ static bool delete_key(json_object *jobj, const char *desc, uint16_t idx)
 	return save_config();
 }
 
+bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx)
+{
+	json_object *jnode;
+
+	if (!cfg || !cfg->jcfg)
+		return false;
+
+	jnode = get_node_by_unicast(unicast);
+	if (!jnode)
+		return false;
+
+	return add_node_key(jnode, "netKeys", idx);
+}
+
 bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t net_idx)
 {
 	json_object *jnode;
@@ -642,6 +707,45 @@ bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t net_idx)
 	return delete_key(jnode, "netKeys", net_idx);
 }
 
+static bool key_update(uint16_t unicast, int16_t idx, bool updated,
+							const char *desc)
+{
+	json_object *jnode, *jarray;
+	int i, sz;
+
+	if (!cfg || !cfg->jcfg)
+		return false;
+
+	jnode = get_node_by_unicast(unicast);
+	if (!jnode)
+		return false;
+
+	if (!json_object_object_get_ex(jnode, desc, &jarray))
+		return false;
+
+	sz = json_object_array_length(jarray);
+
+	for (i = 0; i < sz; ++i) {
+		json_object *jentry;
+		int val;
+
+		jentry = json_object_array_get_idx(jarray, i);
+
+		if (!get_int(jentry, "index", &val))
+			continue;
+
+		if ((val == idx) && write_bool(jentry, "updated", updated))
+			return save_config();
+	}
+
+	return false;
+}
+
+bool mesh_db_node_net_key_update(uint16_t unicast, uint16_t idx, bool updated)
+{
+	return key_update(unicast, idx, updated, "netKeys");
+}
+
 bool mesh_db_node_app_key_add(uint16_t unicast, uint16_t idx)
 {
 	json_object *jnode;
@@ -670,6 +774,11 @@ bool mesh_db_node_app_key_del(uint16_t unicast, uint16_t idx)
 	return delete_key(jnode, "appKeys", idx);
 }
 
+bool mesh_db_node_app_key_update(uint16_t unicast, uint16_t idx, bool updated)
+{
+	return key_update(unicast, idx, updated, "appKeys");
+}
+
 static bool load_keys(json_object *jobj)
 {
 	json_object *jarray, *jentry;
diff --git a/tools/mesh/mesh-db.h b/tools/mesh/mesh-db.h
index efd579553..c1bcb3ae6 100644
--- a/tools/mesh/mesh-db.h
+++ b/tools/mesh/mesh-db.h
@@ -38,8 +38,10 @@ bool mesh_db_node_set_net_transmit(uint16_t unicast, uint8_t cnt,
 							uint16_t interval);
 bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx);
 bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t idx);
+bool mesh_db_node_net_key_update(uint16_t unicast, uint16_t idx, bool updated);
 bool mesh_db_node_app_key_add(uint16_t unicast, uint16_t idx);
 bool mesh_db_node_app_key_del(uint16_t unicast, uint16_t idx);
+bool mesh_db_node_app_key_update(uint16_t unicast, uint16_t idx, bool updated);
 bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl);
 bool mesh_db_node_write_mode(uint16_t unicast, const char *keyword, int value);
 bool mesh_db_node_model_binding_add(uint16_t unicast, uint8_t ele, bool vendor,
diff --git a/tools/mesh/remote.c b/tools/mesh/remote.c
index e60a3681d..5f598cb8b 100644
--- a/tools/mesh/remote.c
+++ b/tools/mesh/remote.c
@@ -25,6 +25,11 @@
 
 #define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
 
+struct remote_key {
+	uint16_t idx;
+	bool updated;
+};
+
 struct remote_node {
 	uint16_t unicast;
 	struct l_queue *net_keys;
@@ -42,20 +47,6 @@ struct rejected_addr {
 static struct l_queue *nodes;
 static struct l_queue *reject_list;
 
-static bool key_present(struct l_queue *keys, uint16_t app_idx)
-{
-	const struct l_queue_entry *l;
-
-	for (l = l_queue_get_entries(keys); l; l = l->next) {
-		uint16_t idx = L_PTR_TO_UINT(l->data);
-
-		if (idx == app_idx)
-			return true;
-	}
-
-	return false;
-}
-
 static int compare_mod_id(const void *a, const void *b, void *user_data)
 {
 	uint32_t id1 = L_PTR_TO_UINT(a);
@@ -102,12 +93,20 @@ static bool match_node_addr(const void *a, const void *b)
 	return false;
 }
 
+static bool match_key(const void *a, const void *b)
+{
+	const struct remote_key *key = a;
+	uint16_t idx = L_PTR_TO_UINT(b);
+
+	return (key->idx == idx);
+}
+
 static bool match_bound_key(const void *a, const void *b)
 {
-	uint16_t app_idx = L_PTR_TO_UINT(a);
+	const struct remote_key *app_key = a;
 	uint16_t net_idx = L_PTR_TO_UINT(b);
 
-	return (net_idx == keys_get_bound_key(app_idx));
+	return (net_idx == keys_get_bound_key(app_key->idx));
 }
 
 uint8_t remote_del_node(uint16_t unicast)
@@ -142,6 +141,7 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
 					uint8_t ele_cnt, uint16_t net_idx)
 {
 	struct remote_node *rmt;
+	struct remote_key *key;
 
 	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(unicast));
 	if (rmt)
@@ -153,7 +153,10 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
 	rmt->num_ele = ele_cnt;
 	rmt->net_keys = l_queue_new();
 
-	l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
+	key = l_new(struct remote_key, 1);
+	key->idx = net_idx;
+
+	l_queue_push_tail(rmt->net_keys, key);
 
 	rmt->els = l_new(struct l_queue *, ele_cnt);
 
@@ -161,6 +164,7 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
 		nodes = l_queue_new();
 
 	l_queue_insert(nodes, rmt, compare_unicast, NULL);
+
 	return true;
 }
 
@@ -188,49 +192,84 @@ bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
 	return true;
 }
 
-bool remote_add_net_key(uint16_t addr, uint16_t net_idx)
+bool remote_add_net_key(uint16_t addr, uint16_t net_idx, bool save)
 {
 	struct remote_node *rmt;
+	struct remote_key *key;
 
 	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
 	if (!rmt)
 		return false;
 
-	if (key_present(rmt->net_keys, net_idx))
-		return false;
+	if (l_queue_find(rmt->net_keys, match_key, L_UINT_TO_PTR(net_idx)))
+		return true;
 
-	l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
-	return true;
+	key = l_new(struct remote_key, 1);
+	key->idx = net_idx;
+
+	l_queue_push_tail(rmt->net_keys, key);
+
+	if (save)
+		return mesh_db_node_net_key_add(addr, net_idx);
+	else
+		return true;
 }
 
 bool remote_del_net_key(uint16_t addr, uint16_t net_idx)
 {
 	struct remote_node *rmt;
-	void *data;
+	struct remote_key *key;
 
 	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
 	if (!rmt)
 		return false;
 
-	if (!l_queue_remove(rmt->net_keys, L_UINT_TO_PTR(net_idx)))
+	key = l_queue_remove_if(rmt->net_keys, match_key,
+							L_UINT_TO_PTR(net_idx));
+	if (!key)
 		return false;
 
-	data = l_queue_remove_if(rmt->app_keys, match_bound_key,
+	mesh_db_node_net_key_del(addr, net_idx);
+
+	l_free(key);
+	key = l_queue_remove_if(rmt->app_keys, match_bound_key,
 						L_UINT_TO_PTR(net_idx));
-	while (data) {
-		uint16_t app_idx = (uint16_t) L_PTR_TO_UINT(data);
 
-		mesh_db_node_app_key_del(rmt->unicast, app_idx);
-		data = l_queue_remove_if(rmt->app_keys, match_bound_key,
+	while (key) {
+		mesh_db_node_app_key_del(rmt->unicast, key->idx);
+		l_free(key);
+
+		key = l_queue_remove_if(rmt->app_keys, match_bound_key,
 						L_UINT_TO_PTR(net_idx));
 	}
 
 	return true;
 }
 
-bool remote_add_app_key(uint16_t addr, uint16_t app_idx)
+bool remote_update_net_key(uint16_t addr, uint16_t net_idx, bool update,
+								bool save)
+{
+	struct remote_node *rmt;
+	struct remote_key *key;
+
+	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
+	if (!rmt)
+		return false;
+
+	key = l_queue_find(rmt->net_keys, match_key,
+						L_UINT_TO_PTR(net_idx));
+	key->updated = update;
+
+	if (save)
+		return mesh_db_node_net_key_update(addr, net_idx, update);
+	else
+		return true;
+}
+
+bool remote_add_app_key(uint16_t addr, uint16_t app_idx, bool save)
 {
 	struct remote_node *rmt;
+	struct remote_key *key;
 
 	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
 	if (!rmt)
@@ -239,44 +278,105 @@ bool remote_add_app_key(uint16_t addr, uint16_t app_idx)
 	if (!rmt->app_keys)
 		rmt->app_keys = l_queue_new();
 
-	if (key_present(rmt->app_keys, app_idx))
-		return false;
+	if (l_queue_find(rmt->app_keys, match_key, L_UINT_TO_PTR(app_idx)))
+		return true;
 
-	l_queue_push_tail(rmt->app_keys, L_UINT_TO_PTR(app_idx));
-	return true;
+	key = l_new(struct remote_key, 1);
+	key->idx = app_idx;
+
+	l_queue_push_tail(rmt->app_keys, key);
+
+	if (save)
+		return mesh_db_node_app_key_add(addr, app_idx);
+	else
+		return true;
 }
 
 bool remote_del_app_key(uint16_t addr, uint16_t app_idx)
 {
 	struct remote_node *rmt;
+	struct remote_key *key;
+
+	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
+	if (!rmt)
+		return false;
+
+	key = l_queue_remove_if(rmt->app_keys, match_key,
+						L_UINT_TO_PTR(app_idx));
+	l_free(key);
+
+	return mesh_db_node_app_key_del(addr, app_idx);
+}
+
+bool remote_update_app_key(uint16_t addr, uint16_t app_idx, bool update,
+								bool save)
+{
+	struct remote_node *rmt;
+	struct remote_key *key;
 
 	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
 	if (!rmt)
 		return false;
 
-	return l_queue_remove(rmt->app_keys, L_UINT_TO_PTR(app_idx));
+	key = l_queue_find(rmt->app_keys, match_key,
+						L_UINT_TO_PTR(app_idx));
+	key->updated = update;
+
+	if (save)
+		return mesh_db_node_app_key_update(addr, app_idx, update);
+	else
+		return true;
+}
+
+void remote_finish_key_refresh(uint16_t addr, uint16_t net_idx)
+{
+	struct remote_node *rmt;
+	struct remote_key *key;
+	const struct l_queue_entry *l;
+
+	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
+	if (!rmt)
+		return;
+
+	if (!remote_update_net_key(addr, net_idx, false, true))
+		return;
+
+	l = l_queue_get_entries(rmt->app_keys);
+
+	for (; l; l = l->next) {
+		key = l->data;
+
+		if (net_idx != keys_get_bound_key(key->idx))
+			continue;
+
+		key->updated = false;
+
+		mesh_db_node_app_key_update(addr, key->idx, false);
+	}
+
 }
 
 uint16_t remote_get_subnet_idx(uint16_t addr)
 {
 	struct remote_node *rmt;
-	uint32_t net_idx;
+	struct remote_key *key;
 
 	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
 
 	if (!rmt || l_queue_isempty(rmt->net_keys))
 		return NET_IDX_INVALID;
 
-	net_idx = L_PTR_TO_UINT(l_queue_peek_head(rmt->net_keys));
+	key = l_queue_peek_head(rmt->net_keys);
 
-	return (uint16_t) net_idx;
+	return key->idx;
 }
 
-static void print_key(void *key, void *user_data)
+static void print_key(void *data, void *user_data)
 {
-	uint16_t idx = L_PTR_TO_UINT(key);
+	struct remote_key *key = data;
 
-	bt_shell_printf("%u (0x%3.3x), ", idx, idx);
+	bt_shell_printf("%u (0x%3.3x) %s, ", key->idx, key->idx,
+						key->updated ? ", updated":"");
 }
 
 static void print_model(void *model, void *user_data)
diff --git a/tools/mesh/remote.h b/tools/mesh/remote.h
index 8ecb097ae..74747689a 100644
--- a/tools/mesh/remote.h
+++ b/tools/mesh/remote.h
@@ -16,10 +16,15 @@ bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
 void remote_add_rejected_address(uint16_t addr, uint32_t iv_index, bool save);
 void remote_clear_rejected_addresses(uint32_t iv_index);
 uint16_t remote_get_next_unicast(uint16_t low, uint16_t high, uint8_t ele_cnt);
-bool remote_add_net_key(uint16_t addr, uint16_t net_idx);
+bool remote_add_net_key(uint16_t addr, uint16_t net_idx, bool save);
 bool remote_del_net_key(uint16_t addr, uint16_t net_idx);
-bool remote_add_app_key(uint16_t addr, uint16_t app_idx);
+bool remote_update_net_key(uint16_t addr, uint16_t net_idx, bool update,
+								bool save);
+bool remote_add_app_key(uint16_t addr, uint16_t app_idx, bool save);
 bool remote_del_app_key(uint16_t addr, uint16_t app_idx);
+bool remote_update_app_key(uint16_t addr, uint16_t app_idx, bool update,
+								bool save);
+void remote_finish_key_refresh(uint16_t addr, uint16_t net_idx);
 uint16_t remote_get_subnet_idx(uint16_t addr);
 void remote_print_node(uint16_t addr);
 void remote_print_all(void);
-- 
2.31.1


  parent reply	other threads:[~2021-09-23  3:27 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-23  3:25 [PATCH BlueZ 00/20] Mesh Configuration Database Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 01/20] tools/mesh-cfgclient: Save provisioner info Inga Stotland
2021-09-23  4:00   ` Mesh Configuration Database bluez.test.bot
2021-09-23  4:14     ` Tedd Ho-Jeong An
2021-09-23 16:52   ` bluez.test.bot
2021-09-23  3:25 ` [PATCH BlueZ 02/20] tools/mesh-cfgclient: Add timestamp to config database Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 03/20] tools/mesh-cfgclient: Update stored NetKey and AppKey Inga Stotland
2021-09-23  3:25 ` Inga Stotland [this message]
2021-09-23  3:25 ` [PATCH BlueZ 05/20] tools/mesh: Add new info to stored remote nodes Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 06/20] tools/mesh-cfgclient: Overwrite config values when adding new ones Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 07/20] tools/mesh-cfgclient: Store remote node's model bindings Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 08/20] tools/mesh-cfgclient: Store remote node's model subs Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 09/20] tools/mesh-cfgclient: Disallow model commands w/o composition Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 10/20] tools/mesh-cfgclient: Store remote's model publication info Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 11/20] tools/mesh-cfgclient: Check the result of config save Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 12/20] tools/mesh-cfgclient: Rename mesh-db APIs for consistency Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 13/20] tools/mesh-cfgclient: Save remote node feature setting Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 14/20] tools/mesh-cfgclient: Store remote's heartbeat sub/pub Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 15/20] tools/mesh-cfgclient: Add group parent address for DB compliance Inga Stotland
2021-09-23  3:25 ` [PATCH BlueZ 16/20] doc/mesh-api: Add ExportKeys call Inga Stotland
2021-09-23  3:26 ` [PATCH BlueZ 17/20] mesh: Implement ExportKeys() method Inga Stotland
2021-09-23  3:26 ` [PATCH BlueZ 18/20] tools/mesh-cfgclient: Store UUIDs in standard format Inga Stotland
2021-09-23  3:26 ` [PATCH BlueZ 19/20] tools/mesh-cfgclient: Excluded addresses property Inga Stotland
2021-09-23  3:26 ` [PATCH BlueZ 20/20] tools/mesh-cfgclient: Export configuration database Inga Stotland
2021-09-27 20:27 ` [PATCH BlueZ 00/20] Mesh Configuration Database Gix, Brian

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210923032603.50536-5-inga.stotland@intel.com \
    --to=inga.stotland@intel.com \
    --cc=brian.gix@intel.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.