Re: [PATCH BlueZ v2] mesh: Refactor Secure Network Beaconing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Applied

On Fri, 2019-12-13 at 12:15 -0800, Brian Gix wrote:
> The daemon handles multiple nodes, that may or may not be on the same
> mesh network.  While each node my be seperately configured to beacon or
> not beacon, there is nothing gained (except redundent traffic) for each
> node to beacon seperately.  Beaconing is therefore centralized with the
> Network Key the SNB represents, with each *received* beacon delivered
> to each node. But for SNBs generated, we keep a count of how many nodes
> want beacons sent for a specific key. If 1 or more, we beacon, if 0
> nodes want the beacon sent, then we do not beacon.
> ---
>  mesh/mesh-io.c  |   3 +
>  mesh/net-keys.c | 204 +++++++++++++++++++++++++++-
>  mesh/net-keys.h |   8 ++
>  mesh/net.c      | 350 ++++++++++++++++--------------------------------
>  mesh/net.h      |   3 +
>  5 files changed, 326 insertions(+), 242 deletions(-)
> 
> diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
> index 95a99b6a5..1ab173d9c 100644
> --- a/mesh/mesh-io.c
> +++ b/mesh/mesh-io.c
> @@ -171,6 +171,9 @@ bool mesh_io_send(struct mesh_io *io, struct mesh_io_send_info *info,
>  {
>  	io = l_queue_find(io_list, match_by_io, io);
>  
> +	if (!io)
> +		io = l_queue_peek_head(io_list);
> +
>  	if (io && io->api && io->api->send)
>  		return io->api->send(io, info, data, len);
>  
> diff --git a/mesh/net-keys.c b/mesh/net-keys.c
> index 5be7e0b58..65f0808dd 100644
> --- a/mesh/net-keys.c
> +++ b/mesh/net-keys.c
> @@ -23,16 +23,35 @@
>  
>  #include <ell/ell.h>
>  
> +#include "mesh/mesh-defs.h"
> +#include "mesh/util.h"
>  #include "mesh/crypto.h"
> +#include "mesh/mesh-io.h"
> +#include "mesh/net.h"
>  #include "mesh/net-keys.h"
>  
>  #define BEACON_TYPE_SNB		0x01
>  #define KEY_REFRESH		0x01
>  #define IV_INDEX_UPDATE		0x02
>  
> +#define BEACON_INTERVAL_MIN	10
> +#define BEACON_INTERVAL_MAX	600
> +
> +struct net_beacon {
> +	struct l_timeout *timeout;
> +	uint32_t ts;
> +	uint16_t observe_period;
> +	uint16_t observed;
> +	uint16_t expected;
> +	bool half_period;
> +	uint8_t beacon[23];
> +};
> +
>  struct net_key {
>  	uint32_t id;
> +	struct net_beacon snb;
>  	uint16_t ref_cnt;
> +	uint16_t beacon_enables;
>  	uint8_t friend_key;
>  	uint8_t nid;
>  	uint8_t master[16];
> @@ -157,6 +176,7 @@ void net_key_unref(uint32_t id)
>  
>  	if (key && key->ref_cnt) {
>  		if (--key->ref_cnt == 0) {
> +			l_timeout_remove(key->snb.timeout);
>  			l_queue_remove(keys, key);
>  			l_free(key);
>  		}
> @@ -305,18 +325,188 @@ bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
>  		return false;
>  	}
>  
> -	snb[0] = BEACON_TYPE_SNB;
> -	snb[1] = 0;
> +	snb[0] = MESH_AD_TYPE_BEACON;
> +	snb[1] = BEACON_TYPE_SNB;
> +	snb[2] = 0;
>  
>  	if (kr)
> -		snb[1] |= KEY_REFRESH;
> +		snb[2] |= KEY_REFRESH;
>  
>  	if (ivu)
> -		snb[1] |= IV_INDEX_UPDATE;
> +		snb[2] |= IV_INDEX_UPDATE;
>  
> -	memcpy(snb + 2, key->network, 8);
> -	l_put_be32(iv_index, snb + 10);
> -	l_put_be64(cmac, snb + 14);
> +	memcpy(snb + 3, key->network, 8);
> +	l_put_be32(iv_index, snb + 11);
> +	l_put_be64(cmac, snb + 15);
>  
>  	return true;
>  }
> +
> +static void send_network_beacon(struct net_key *key)
> +{
> +	struct mesh_io_send_info info = {
> +		.type = MESH_IO_TIMING_TYPE_GENERAL,
> +		.u.gen.interval = 100,
> +		.u.gen.cnt = 1,
> +		.u.gen.min_delay = DEFAULT_MIN_DELAY,
> +		.u.gen.max_delay = DEFAULT_MAX_DELAY
> +	};
> +
> +	mesh_io_send(NULL, &info, key->snb.beacon, sizeof(key->snb.beacon));
> +}
> +
> +static void snb_timeout(struct l_timeout *timeout, void *user_data)
> +{
> +	struct net_key *key = user_data;
> +	uint32_t interval, scale_factor;
> +
> +	/* Always send at least one beacon */
> +	send_network_beacon(key);
> +
> +	/* Count our own beacons towards the vicinity total */
> +	key->snb.observed++;
> +
> +	if (!key->snb.half_period) {
> +
> +		l_debug("beacon %d for %d nodes, period %d, obs %d, exp %d",
> +						key->id,
> +						key->beacon_enables,
> +						key->snb.observe_period,
> +						key->snb.observed,
> +						key->snb.expected);
> +
> +
> +		interval = (key->snb.observe_period * key->snb.observed)
> +							/ key->snb.expected;
> +
> +		/* Limit Increases and Decreases by 10 seconds Up and
> +		 * 20 seconds down each step, to avoid going nearly silent
> +		 * in highly populated environments.
> +		 */
> +		if (interval - 10 > key->snb.observe_period)
> +			interval = key->snb.observe_period + 10;
> +		else if (interval + 20 < key->snb.observe_period)
> +			interval = key->snb.observe_period - 20;
> +
> +		/* Beaconing must be no *slower* than once every 10 minutes,
> +		 * and no *faster* than once every 10 seconds, per spec.
> +		 * Observation period is twice beaconing period.
> +		 */
> +		if (interval < BEACON_INTERVAL_MIN * 2)
> +			interval = BEACON_INTERVAL_MIN * 2;
> +		else if (interval > BEACON_INTERVAL_MAX * 2)
> +			interval = BEACON_INTERVAL_MAX * 2;
> +
> +		key->snb.observe_period = interval;
> +		key->snb.observed = 0;
> +
> +		/* To prevent "over slowing" of the beaconing frequency,
> +		 * require more significant "over observing" the slower
> +		 * our own beaconing frequency.
> +		 */
> +		key->snb.expected = interval / 10;
> +		scale_factor = interval / 60;
> +		key->snb.expected += scale_factor * 3;
> +	}
> +
> +	interval = key->snb.observe_period / 2;
> +	key->snb.ts = get_timestamp_secs();
> +	key->snb.half_period = !key->snb.half_period;
> +
> +	if (key->beacon_enables)
> +		l_timeout_modify(timeout, interval);
> +	else {
> +		l_timeout_remove(timeout);
> +		key->snb.timeout = NULL;
> +	}
> +}
> +
> +void net_key_beacon_seen(uint32_t id)
> +{
> +	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
> +
> +	if (key)
> +		key->snb.observed++;
> +}
> +
> +void net_key_beacon_enable(uint32_t id)
> +{
> +	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
> +	bool enabled;
> +	uint32_t rand_ms;
> +
> +	if (!key)
> +		return;
> +
> +	enabled = !!key->beacon_enables;
> +	key->beacon_enables++;
> +
> +	/* If already Enabled, do nothing */
> +	if (enabled)
> +		return;
> +
> +	/* Randomize first timeout to avoid bursts of beacons */
> +	l_getrandom(&rand_ms, sizeof(rand_ms));
> +	rand_ms %= (BEACON_INTERVAL_MIN * 1000);
> +	rand_ms++;
> +
> +	/* Enable Periodic Beaconing on this key */
> +	key->snb.ts = get_timestamp_secs();
> +	key->snb.observe_period = BEACON_INTERVAL_MIN * 2;
> +	key->snb.expected = 2;
> +	key->snb.observed = 0;
> +	key->snb.half_period = true;
> +	l_timeout_remove(key->snb.timeout);
> +	key->snb.timeout = l_timeout_create_ms(rand_ms, snb_timeout, key, NULL);
> +}
> +
> +bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu)
> +{
> +	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
> +	uint8_t beacon[23];
> +	uint32_t rand_ms;
> +
> +	if (!key)
> +		return false;
> +
> +	if (!net_key_snb_compose(id, iv_index, kr, ivu, beacon))
> +		return false;
> +
> +	if (memcmp(key->snb.beacon, beacon, sizeof(beacon)))
> +		memcpy(key->snb.beacon, beacon, sizeof(beacon));
> +	else
> +		return false;
> +
> +	l_debug("Setting SNB: IVI: %8.8x, IVU: %d, KR: %d", iv_index, ivu, kr);
> +	print_packet("Set SNB Beacon to", beacon, sizeof(beacon));
> +
> +	/* Send one new SNB soon, after all nodes have seen it */
> +	l_getrandom(&rand_ms, sizeof(rand_ms));
> +	rand_ms %= 1000;
> +	key->snb.expected++;
> +
> +	if (key->snb.timeout)
> +		l_timeout_modify_ms(key->snb.timeout, 500 + rand_ms);
> +	else
> +		key->snb.timeout = l_timeout_create_ms(500 + rand_ms,
> +						snb_timeout, key, NULL);
> +
> +	return true;
> +}
> +
> +void net_key_beacon_disable(uint32_t id)
> +{
> +	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
> +
> +	if (!key || !key->beacon_enables)
> +		return;
> +
> +	key->beacon_enables--;
> +
> +	if (key->beacon_enables)
> +		return;
> +
> +	/* Disable periodic Beaconing on this key */
> +	l_timeout_remove(key->snb.timeout);
> +	key->snb.timeout = NULL;
> +}
> diff --git a/mesh/net-keys.h b/mesh/net-keys.h
> index d54c52156..3c2c4d0da 100644
> --- a/mesh/net-keys.h
> +++ b/mesh/net-keys.h
> @@ -17,6 +17,10 @@
>   *
>   */
>  
> +#define BEACON_TYPE_SNB		0x01
> +#define KEY_REFRESH		0x01
> +#define IV_INDEX_UPDATE		0x02
> +
>  bool net_key_confirm(uint32_t id, const uint8_t master[16]);
>  bool net_key_retrieve(uint32_t id, uint8_t *master);
>  uint32_t net_key_add(const uint8_t master[16]);
> @@ -31,3 +35,7 @@ bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
>  								uint64_t cmac);
>  bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
>  								uint8_t *snb);
> +void net_key_beacon_seen(uint32_t id);
> +void net_key_beacon_enable(uint32_t id);
> +bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu);
> +void net_key_beacon_disable(uint32_t id);
> diff --git a/mesh/net.c b/mesh/net.c
> index f662d8a91..e708b2aa4 100644
> --- a/mesh/net.c
> +++ b/mesh/net.c
> @@ -53,15 +53,9 @@
>  #define SEG_TO	2
>  #define MSG_TO	60
>  
> -#define DEFAULT_MIN_DELAY		0
> -#define DEFAULT_MAX_DELAY		25
> -
>  #define DEFAULT_TRANSMIT_COUNT		1
>  #define DEFAULT_TRANSMIT_INTERVAL	100
>  
> -#define BEACON_INTERVAL_MIN	10
> -#define BEACON_INTERVAL_MAX	600
> -
>  #define SAR_KEY(src, seq0)	((((uint32_t)(seq0)) << 16) | (src))
>  
>  enum _relay_advice {
> @@ -90,23 +84,12 @@ struct net_key {
>  	uint8_t network_id[8];
>  };
>  
> -struct mesh_beacon {
> -	struct l_timeout *timeout;
> -	uint32_t ts;
> -	uint16_t observe_period;
> -	uint16_t observed;
> -	uint16_t expected;
> -	uint8_t half_period;
> -	uint8_t beacon[23];
> -};
> -
>  struct mesh_subnet {
>  	struct mesh_net *net;
>  	uint16_t idx;
>  	uint32_t net_key_tx;
>  	uint32_t net_key_cur;
>  	uint32_t net_key_upd;
> -	struct mesh_beacon snb;
>  	uint8_t key_refresh;
>  	uint8_t kr_phase;
>  };
> @@ -260,8 +243,11 @@ struct net_queue_data {
>  };
>  
>  struct net_beacon_data {
> -	const uint8_t *data;
> -	uint16_t len;
> +	uint32_t key_id;
> +	uint32_t ivi;
> +	bool ivu;
> +	bool kr;
> +	bool processed;
>  };
>  
>  #define FAST_CACHE_SIZE 8
> @@ -570,9 +556,6 @@ static void subnet_free(void *data)
>  	l_free(subnet);
>  }
>  
> -static void lpn_process_beacon(void *user_data, const void *data, uint8_t size,
> -								int8_t rssi);
> -
>  static struct mesh_subnet *subnet_new(struct mesh_net *net, uint16_t idx)
>  {
>  	struct mesh_subnet *subnet;
> @@ -583,93 +566,71 @@ static struct mesh_subnet *subnet_new(struct mesh_net *net, uint16_t idx)
>  
>  	subnet->net = net;
>  	subnet->idx = idx;
> -	subnet->snb.beacon[0] = MESH_AD_TYPE_BEACON;
>  	return subnet;
>  }
>  
> -static bool create_secure_beacon(struct mesh_net *net,
> -					struct mesh_subnet *subnet,
> -					uint8_t *beacon_data)
> +static void enable_beacon(void *a, void *b)
>  {
> -	bool kr = (subnet->kr_phase == KEY_REFRESH_PHASE_TWO);
> +	struct mesh_subnet *subnet = a;
> +	struct mesh_net *net = b;
>  
> -	return net_key_snb_compose(subnet->net_key_tx, net->iv_index,
> -					kr, net->iv_update, beacon_data);
> +	if (net->beacon_enable)
> +		net_key_beacon_enable(subnet->net_key_tx);
> +	else
> +		net_key_beacon_disable(subnet->net_key_tx);
>  }
>  
> -static void send_network_beacon(struct mesh_subnet *subnet,
> -							struct mesh_net *net)
> +static void enqueue_update(void *a, void *b);
> +
> +static void queue_friend_update(struct mesh_net *net)
>  {
> -	struct mesh_io_send_info info = {
> -		.type = MESH_IO_TIMING_TYPE_GENERAL,
> -		.u.gen.interval = net->tx_interval,
> -		.u.gen.cnt = 1,
> -		.u.gen.min_delay = DEFAULT_MIN_DELAY,
> -		.u.gen.max_delay = DEFAULT_MAX_DELAY
> -	};
> +	struct mesh_subnet *subnet;
> +	struct mesh_friend *frnd;
> +	uint8_t flags = 0;
>  
> -	l_info("Send SNB on network %3.3x", subnet->idx);
> -	mesh_io_send(net->io, &info, subnet->snb.beacon,
> -						sizeof(subnet->snb.beacon));
> -}
> +	if (l_queue_length(net->friends)) {
> +		struct mesh_friend_msg update = {
> +			.src = net->src_addr,
> +			.iv_index = mesh_net_get_iv_index(net),
> +			.last_len = 7,
> +			.ctl = true,
> +		};
>  
> -static void network_beacon_timeout(struct l_timeout *timeout, void *user_data)
> -{
> -	struct mesh_subnet *subnet = user_data;
> -	uint32_t interval;
> +		frnd = l_queue_peek_head(net->friends);
> +		subnet = l_queue_find(net->subnets, match_key_index,
> +						L_UINT_TO_PTR(frnd->net_idx));
>  
> -	send_network_beacon(subnet, subnet->net);
> +		if (!subnet)
> +			return;
>  
> -	if (!subnet->snb.half_period) {
> -		l_debug("beacon TO period %d, observed %d, expected %d",
> -						subnet->snb.observe_period,
> -						subnet->snb.observed,
> -						subnet->snb.expected);
> -		interval = subnet->snb.observe_period *
> -			(subnet->snb.observed + 1) / subnet->snb.expected;
> -		subnet->snb.observe_period = interval * 2;
> -		subnet->snb.expected = subnet->snb.observe_period / 10;
> -		subnet->snb.observed = 0;
> -	} else
> -		interval = subnet->snb.observe_period / 2;
> +		if (subnet->kr_phase == KEY_REFRESH_PHASE_TWO)
> +			flags |= KEY_REFRESH;
>  
> -	if (interval < BEACON_INTERVAL_MIN)
> -		interval = BEACON_INTERVAL_MIN;
> +		if (net->iv_update)
> +			flags |= IV_INDEX_UPDATE;
>  
> -	if (interval > BEACON_INTERVAL_MAX)
> -		interval = BEACON_INTERVAL_MAX;
> +		update.u.one[0].hdr = NET_OP_FRND_UPDATE << OPCODE_HDR_SHIFT;
> +		update.u.one[0].seq = mesh_net_next_seq_num(net);
> +		update.u.one[0].data[0] = NET_OP_FRND_UPDATE;
> +		update.u.one[0].data[1] = flags;
> +		l_put_be32(net->iv_index, update.u.one[0].data + 2);
> +		update.u.one[0].data[6] = 0x01; /* More Data */
> +		/* print_packet("Frnd-Beacon-SRC",
> +		 *			beacon_data, sizeof(beacon_data));
> +		 */
> +		/* print_packet("Frnd-Update", update.u.one[0].data, 6); */
>  
> -	subnet->snb.ts = get_timestamp_secs();
> -	subnet->snb.half_period ^= 1;
> -	l_timeout_modify(timeout, interval);
> +		l_queue_foreach(net->friends, enqueue_update, &update);
> +	}
>  }
>  
> -static void start_network_beacon(void *a, void *b)
> +static void refresh_beacon(void *a, void *b)
>  {
>  	struct mesh_subnet *subnet = a;
>  	struct mesh_net *net = b;
>  
> -	if (!net->beacon_enable) {
> -		if (subnet->snb.timeout)
> -			l_timeout_remove(subnet->snb.timeout);
> -		subnet->snb.timeout = NULL;
> -		return;
> -	}
> -
> -	/* If timeout is active, let it run it's course */
> -	if (subnet->snb.timeout)
> -		return;
> -
> -	send_network_beacon(subnet, subnet->net);
> -
> -	subnet->snb.ts = get_timestamp_secs();
> -	subnet->snb.expected = 2;
> -	subnet->snb.observed = 0;
> -	subnet->snb.half_period = 1;
> -	subnet->snb.observe_period = BEACON_INTERVAL_MIN * 2;
> -
> -	subnet->snb.timeout = l_timeout_create(BEACON_INTERVAL_MIN,
> -				network_beacon_timeout, subnet, NULL);
> +	net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
> +		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
>  }
>  
>  struct mesh_net *mesh_net_new(struct mesh_node *node)
> @@ -1005,10 +966,11 @@ static struct mesh_subnet *add_key(struct mesh_net *net, uint16_t idx,
>  		return NULL;
>  	}
>  
> -	if (!create_secure_beacon(net, subnet, subnet->snb.beacon + 1)) {
> -		subnet_free(subnet);
> -		return NULL;
> -	}
> +	net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
> +						false, net->iv_update);
> +
> +	if (net->beacon_enable)
> +		net_key_beacon_enable(subnet->net_key_tx);
>  
>  	l_queue_push_tail(net->subnets, subnet);
>  
> @@ -1043,9 +1005,6 @@ int mesh_net_add_key(struct mesh_net *net, uint16_t idx, const uint8_t *value)
>  		return MESH_STATUS_STORAGE_FAIL;
>  	}
>  
> -	if (net->io)
> -		start_network_beacon(subnet, net);
> -
>  	return MESH_STATUS_SUCCESS;
>  }
>  
> @@ -1072,11 +1031,11 @@ void mesh_net_get_snb_state(struct mesh_net *net, uint8_t *flags,
>  		return;
>  
>  	*iv_index = net->iv_index;
> -	*flags = (net->iv_upd_state == IV_UPD_UPDATING) ? 0x02 : 0x00;
> +	*flags = net->iv_update ? IV_INDEX_UPDATE : 0x00;
>  
>  	subnet = get_primary_subnet(net);
>  	if (subnet)
> -		*flags |= subnet->key_refresh ? 0x01 : 0x00;
> +		*flags |= subnet->key_refresh ? KEY_REFRESH : 0x00;
>  }
>  
>  bool mesh_net_get_key(struct mesh_net *net, bool new_key, uint16_t idx,
> @@ -2117,14 +2076,6 @@ static bool ctl_received(struct mesh_net *net, uint16_t key_id,
>  						L_UINT_TO_PTR(src)));
>  		break;
>  
> -	case NET_OP_FRND_UPDATE:
> -		if (ttl)
> -			return false;
> -
> -		print_packet("Rx-NET_OP_FRND_UPDATE", pkt, len);
> -		lpn_process_beacon(net, pkt, len, 0);
> -		break;
> -
>  	case NET_OP_FRND_REQUEST:
>  		if (!net->friend_enable)
>  			return false;
> @@ -2539,50 +2490,6 @@ static void net_msg_recv(void *user_data, struct mesh_io_recv_info *info,
>  	}
>  }
>  
> -static void set_network_beacon(void *a, void *b)
> -{
> -	struct mesh_subnet *subnet = a;
> -	struct mesh_net *net = b;
> -	uint8_t beacon_data[22];
> -
> -	if (!create_secure_beacon(net, subnet, beacon_data))
> -		return;
> -
> -	if (memcmp(&subnet->snb.beacon[1], beacon_data,
> -						sizeof(beacon_data)) == 0)
> -		return;
> -
> -	memcpy(&subnet->snb.beacon[1], beacon_data, sizeof(beacon_data));
> -
> -	if (net->beacon_enable && !net->friend_addr) {
> -		print_packet("Set My Beacon to",
> -			beacon_data, sizeof(beacon_data));
> -		start_network_beacon(subnet, net);
> -	}
> -
> -	if (l_queue_length(net->friends)) {
> -		struct mesh_friend_msg update = {
> -			.src = net->src_addr,
> -			.iv_index = mesh_net_get_iv_index(net),
> -			.last_len = 7,
> -			.ctl = true,
> -		};
> -
> -		update.u.one[0].hdr = NET_OP_FRND_UPDATE << OPCODE_HDR_SHIFT;
> -		update.u.one[0].seq = mesh_net_next_seq_num(net);
> -		update.u.one[0].data[0] = NET_OP_FRND_UPDATE;
> -		update.u.one[0].data[1] = beacon_data[3];
> -		l_put_be32(net->iv_index, update.u.one[0].data + 2);
> -		update.u.one[0].data[6] = 0x01; /* More Data */
> -		/* print_packet("Frnd-Beacon-SRC",
> -		 *			beacon_data, sizeof(beacon_data));
> -		 */
> -		/* print_packet("Frnd-Update", update.u.one[0].data, 6); */
> -
> -		l_queue_foreach(net->friends, enqueue_update, &update);
> -	}
> -}
> -
>  static void iv_upd_to(struct l_timeout *upd_timeout, void *user_data)
>  {
>  	struct mesh_net *net = user_data;
> @@ -2604,7 +2511,8 @@ static void iv_upd_to(struct l_timeout *upd_timeout, void *user_data)
>  		net->iv_update = false;
>  		mesh_config_write_iv_index(node_config_get(net->node),
>  							net->iv_index, false);
> -		l_queue_foreach(net->subnets, set_network_beacon, net);
> +		l_queue_foreach(net->subnets, refresh_beacon, net);
> +		queue_friend_update(net);
>  		mesh_net_flush_msg_queues(net);
>  		break;
>  
> @@ -2646,7 +2554,8 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx)
>  	 * it hears beacons from all the nodes
>  	 */
>  	subnet->kr_phase = KEY_REFRESH_PHASE_TWO;
> -	set_network_beacon(subnet, net);
> +	refresh_beacon(subnet, net);
> +	queue_friend_update(net);
>  
>  	l_queue_foreach(net->friends, frnd_kr_phase2, net);
>  
> @@ -2679,7 +2588,8 @@ static int key_refresh_finish(struct mesh_net *net, uint16_t idx)
>  	subnet->net_key_upd = 0;
>  	subnet->key_refresh = 0;
>  	subnet->kr_phase = KEY_REFRESH_PHASE_NONE;
> -	set_network_beacon(subnet, net);
> +	refresh_beacon(subnet, net);
> +	queue_friend_update(net);
>  
>  	l_queue_foreach(net->friends, frnd_kr_phase3, net);
>  
> @@ -2771,106 +2681,73 @@ static void update_iv_ivu_state(struct mesh_net *net, uint32_t iv_index,
>  static void process_beacon(void *net_ptr, void *user_data)
>  {
>  	struct mesh_net *net = net_ptr;
> -	const uint8_t *buf = *(uint8_t **)user_data;
> +	struct net_beacon_data *beacon_data = user_data;
>  	uint32_t ivi;
>  	bool ivu, kr, local_kr;
>  	struct mesh_subnet *subnet;
> -	uint32_t key_id;
>  
> -	ivi = l_get_be32(buf + 10);
> +	ivi = beacon_data->ivi;
>  
>  	/* Ignore out-of-range IV_Index for this network */
>  	if ((net->iv_index + IV_IDX_DIFF_RANGE < ivi) || (ivi < net->iv_index))
>  		return;
>  
> -	/* Ignore Network IDs unknown to this mesh universe */
> -	key_id = net_key_network_id(buf + 2);
> -	if (!key_id)
> -		return;
> -
> +	/* Ignore beacons not in this universe */
>  	subnet = l_queue_find(net->subnets, match_key_id,
> -							L_UINT_TO_PTR(key_id));
> +					L_UINT_TO_PTR(beacon_data->key_id));
> +
>  	if (!subnet)
>  		return;
>  
>  	/* Get IVU and KR boolean bits from beacon */
> -	ivu = !!(buf[1] & 0x02);
> -	kr = !!(buf[1] & 0x01);
> -	local_kr = !!(subnet->kr_phase != KEY_REFRESH_PHASE_TWO);
> -
> -	if (net->iv_upd_state != IV_UPD_INIT) {
> -		/* Ignore beacons that indicate *no change* */
> -		if (!memcmp(&subnet->snb.beacon[1], buf, 22)) {
> -			subnet->snb.observed++;
> -			return;
> -		}
> -	}
> -
> -	/* Validate beacon before accepting */
> -	if (!net_key_snb_check(key_id, ivi, kr, ivu, l_get_be64(buf + 14))) {
> -		l_error("mesh_crypto_beacon verify failed");
> -		return;
> -	}
> +	ivu = beacon_data->ivu;
> +	kr = beacon_data->kr;
> +	local_kr = !!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO);
>  
>  	/* We have officially *seen* this beacon now */
> -	subnet->snb.observed++;
> -
> -	update_iv_ivu_state(net, ivi, ivu);
> -	update_kr_state(subnet, kr, key_id);
> -
> -	if (ivi != net->iv_index || ivu != net->iv_update || kr != local_kr)
> -		set_network_beacon(subnet, net);
> -}
> -
> -static void lpn_process_beacon(void *user_data, const void *data,
> -						uint8_t size, int8_t rssi)
> -{
> -	struct mesh_net *net = user_data;
> -	const uint8_t *buf = data;
> -	uint32_t ivi;
> -	bool ivu, kr, local_kr;
> -	struct mesh_subnet *subnet;
> -	bool kr_transition = false;
> -
> -	/* print_packet("lpn: Secure Net Beacon RXed", data, size); */
> -	kr = !!(buf[0] & 0x01);
> -	ivu = !!(buf[0] & 0x02);
> -	ivi = l_get_be32(buf + 1);
> -
> -	l_debug("KR: %d -- IVU: %d -- IVI: %8.8x", kr, ivu, ivi);
> -
> -	/* TODO: figure out actual network index (i.e., friendship subnet) */
> -	subnet = get_primary_subnet(net);
> -	if (!subnet)
> -		return;
> -
> -	local_kr = (subnet->kr_phase == KEY_REFRESH_PHASE_TWO);
> +	beacon_data->processed = true;
>  
> -	/* Don't bother going further if nothing has changed */
> -	if (local_kr == kr && ivi == net->iv_index && ivu == net->iv_update &&
> -					net->iv_upd_state != IV_UPD_INIT)
> +	if (ivi == net->iv_index && ivu == net->iv_update && kr == local_kr)
>  		return;
>  
>  	update_iv_ivu_state(net, ivi, ivu);
> -
> -	if (kr)
> -		update_kr_state(subnet, kr_transition, subnet->net_key_upd);
> -	else
> -		update_kr_state(subnet, kr_transition, subnet->net_key_cur);
> +	update_kr_state(subnet, kr, beacon_data->key_id);
> +	net_key_beacon_refresh(beacon_data->key_id, net->iv_index,
> +		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
>  }
>  
>  static void beacon_recv(void *user_data, struct mesh_io_recv_info *info,
>  					const uint8_t *data, uint16_t len)
>  {
> -	const uint8_t *ptr = data + 1;
> +	struct net_beacon_data beacon_data = {
> +		.processed = false,
> +	};
>  
>  	if (len != 23 || data[1] != 0x01)
>  		return;
>  
> -	l_debug("KR: %d -- IVU: %d -- IV: %8.8x",
> -			data[2] & 1, !!(data[2] & 2), l_get_be32(data + 11));
> +	/* Ignore Network IDs unknown to this daemon */
> +	beacon_data.key_id = net_key_network_id(data + 3);
> +	if (!beacon_data.key_id)
> +		return;
> +
> +	/* Get data bits from beacon */
> +	beacon_data.ivu = !!(data[2] & 0x02);
> +	beacon_data.kr = !!(data[2] & 0x01);
> +	beacon_data.ivi = l_get_be32(data + 11);
>  
> -	l_queue_foreach(nets, process_beacon, &ptr);
> +	/* Validate beacon before accepting */
> +	if (!net_key_snb_check(beacon_data.key_id, beacon_data.ivi,
> +					beacon_data.kr, beacon_data.ivu,
> +					l_get_be64(data + 15))) {
> +		l_error("mesh_crypto_beacon verify failed");
> +		return;
> +	}
> +
> +	l_queue_foreach(nets, process_beacon, &beacon_data);
> +
> +	if (beacon_data.processed)
> +		net_key_beacon_seen(beacon_data.key_id);
>  }
>  
>  bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable)
> @@ -2878,16 +2755,16 @@ bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable)
>  	if (!net || !IS_UNASSIGNED(net->friend_addr))
>  		return false;
>  
> -	if (net->beacon_enable != enable) {
> -		uint8_t type = MESH_AD_TYPE_BEACON;
> +	if (net->beacon_enable == enable)
> +		return true;
>  
> -		net->beacon_enable = enable;
> +	net->beacon_enable = enable;
>  
> -		if (!enable)
> -			mesh_io_send_cancel(net->io, &type, 1);
> +	if (enable)
> +		l_queue_foreach(net->subnets, refresh_beacon, net);
>  
> -		l_queue_foreach(net->subnets, start_network_beacon, net);
> -	}
> +	l_queue_foreach(net->subnets, enable_beacon, net);
> +	queue_friend_update(net);
>  
>  	return true;
>  }
> @@ -2923,14 +2800,18 @@ bool mesh_net_set_key(struct mesh_net *net, uint16_t idx, const uint8_t *key,
>  	if (phase == KEY_REFRESH_PHASE_TWO) {
>  		subnet->key_refresh = 1;
>  		subnet->net_key_tx = subnet->net_key_upd;
> +		if (net->beacon_enable) {
> +			/* Switch beaconing key */
> +			net_key_beacon_disable(subnet->net_key_cur);
> +			net_key_beacon_enable(subnet->net_key_upd);
> +		}
>  	}
>  
>  	subnet->kr_phase = phase;
>  
> -	set_network_beacon(subnet, net);
> +	net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
> +		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
>  
> -	if (net->io)
> -		start_network_beacon(subnet, net);
>  
>  	return true;
>  }
> @@ -2960,7 +2841,6 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
>  							beacon_recv, NULL);
>  		mesh_io_register_recv_cb(io, MESH_IO_FILTER_NET,
>  							net_msg_recv, NULL);
> -		l_queue_foreach(net->subnets, start_network_beacon, net);
>  	}
>  
>  	if (l_queue_find(nets, is_this_net, net))
> @@ -3007,7 +2887,8 @@ bool mesh_net_iv_index_update(struct mesh_net *net)
>  	net->iv_upd_state = IV_UPD_UPDATING;
>  	net->iv_index++;
>  	net->iv_update = true;
> -	l_queue_foreach(net->subnets, set_network_beacon, net);
> +	l_queue_foreach(net->subnets, refresh_beacon, net);
> +	queue_friend_update(net);
>  	net->iv_update_timeout = l_timeout_create(
>  			IV_IDX_UPD_MIN,
>  			iv_upd_to, net, NULL);
> @@ -3059,7 +2940,6 @@ bool mesh_net_set_friend(struct mesh_net *net, uint16_t friend_addr)
>  
>  	net->friend_addr = friend_addr;
>  
> -	set_network_beacon(get_primary_subnet(net), net);
>  	return true;
>  }
>  
> diff --git a/mesh/net.h b/mesh/net.h
> index fe4e0b653..90ca8328b 100644
> --- a/mesh/net.h
> +++ b/mesh/net.h
> @@ -117,6 +117,9 @@ struct mesh_node;
>  #define FRND_OPCODE(x) \
>  		((x) >= NET_OP_FRND_POLL && (x) <= NET_OP_FRND_CLEAR_CONFIRM)
>  
> +#define DEFAULT_MIN_DELAY		0
> +#define DEFAULT_MAX_DELAY		25
> +
>  struct mesh_net_addr_range {
>  	uint16_t low;
>  	uint16_t high;




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux