* [PATCH BlueZ v2] mesh: rework incoming advertisement filtering
@ 2020-02-24 21:47 Brian Gix
2020-02-26 19:23 ` Gix, Brian
0 siblings, 1 reply; 2+ messages in thread
From: Brian Gix @ 2020-02-24 21:47 UTC (permalink / raw)
To: linux-bluetooth; +Cc: brian.gix, inga.stotland
Future versions of Mesh will introduce new advertising packets, which
do not fit in the limited and rigid filtering currently used. This minor
rewrite allows registering and receiving of *any* AD types, including
the filtering on multiple octets of the incoming AD parts.
---
mesh/manager.c | 5 +-
mesh/mesh-io-api.h | 12 ++--
mesh/mesh-io-generic.c | 150 ++++++++++++++++++++++++-----------------
mesh/mesh-io.c | 36 ++--------
mesh/mesh-io.h | 25 +++----
mesh/mesh.c | 10 ++-
mesh/net.c | 13 ++--
7 files changed, 128 insertions(+), 123 deletions(-)
diff --git a/mesh/manager.c b/mesh/manager.c
index e4a7deaeb..0909c7e16 100644
--- a/mesh/manager.c
+++ b/mesh/manager.c
@@ -52,6 +52,7 @@ static uint8_t scan_uuid[16];
static struct mesh_node *scan_node;
static struct l_timeout *scan_timeout;
static struct add_data *add_pending;
+static const uint8_t prvb[2] = {MESH_AD_TYPE_BEACON, 0x00};
static void scan_cancel(struct l_timeout *timeout, void *user_data)
{
@@ -66,7 +67,7 @@ static void scan_cancel(struct l_timeout *timeout, void *user_data)
net = node_get_net(node);
io = mesh_net_get_io(net);
- mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_PROV_BEACON);
+ mesh_io_deregister_recv_cb(io, prvb, sizeof(prvb));
scan_node = NULL;
scan_timeout = NULL;
}
@@ -397,7 +398,7 @@ static struct l_dbus_message *start_scan_call(struct l_dbus *dbus,
net = node_get_net(node);
io = mesh_net_get_io(net);
scan_node = node;
- mesh_io_register_recv_cb(io, MESH_IO_FILTER_PROV_BEACON,
+ mesh_io_register_recv_cb(io, prvb, sizeof(prvb),
prov_beacon_recv, node);
if (duration)
diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h
index 75b881800..7a5b49c60 100644
--- a/mesh/mesh-io-api.h
+++ b/mesh/mesh-io-api.h
@@ -26,12 +26,11 @@ typedef bool (*mesh_io_caps_t)(struct mesh_io *io, struct mesh_io_caps *caps);
typedef bool (*mesh_io_send_t)(struct mesh_io *io,
struct mesh_io_send_info *info,
const uint8_t *data, uint16_t len);
-typedef bool (*mesh_io_register_t)(struct mesh_io *io, uint8_t filter_id,
- mesh_io_recv_func_t cb, void *user_data);
-typedef bool (*mesh_io_deregister_t)(struct mesh_io *io, uint8_t filter_id);
-typedef bool (*mesh_io_filter_set_t)(struct mesh_io *io,
- uint8_t filter_id, const uint8_t *data, uint8_t len,
- mesh_io_status_func_t callback, void *user_data);
+typedef bool (*mesh_io_register_t)(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len, mesh_io_recv_func_t cb,
+ void *user_data);
+typedef bool (*mesh_io_deregister_t)(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len);
typedef bool (*mesh_io_tx_cancel_t)(struct mesh_io *io, const uint8_t *pattern,
uint8_t len);
@@ -42,7 +41,6 @@ struct mesh_io_api {
mesh_io_send_t send;
mesh_io_register_t reg;
mesh_io_deregister_t dereg;
- mesh_io_filter_set_t set;
mesh_io_tx_cancel_t cancel;
};
diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
index b42fb4f1d..2efd32f12 100644
--- a/mesh/mesh-io-generic.c
+++ b/mesh/mesh-io-generic.c
@@ -31,6 +31,7 @@
#include "lib/bluetooth.h"
#include "lib/mgmt.h"
+#include "mesh/mesh-defs.h"
#include "mesh/mesh-mgmt.h"
#include "mesh/mesh-io.h"
#include "mesh/mesh-io-api.h"
@@ -44,16 +45,17 @@ struct mesh_io_private {
struct l_queue *rx_regs;
struct l_queue *tx_pkts;
struct tx_pkt *tx;
- uint8_t filters[4];
- bool sending;
uint16_t index;
uint16_t interval;
+ bool sending;
+ bool active;
};
struct pvt_rx_reg {
- uint8_t filter_id;
mesh_io_recv_func_t cb;
void *user_data;
+ uint8_t len;
+ uint8_t filter[0];
};
struct process_data {
@@ -93,20 +95,17 @@ static uint32_t instant_remaining_ms(uint32_t instant)
return instant;
}
-static void process_rx_callbacks(void *v_rx, void *v_reg)
+static void process_rx_callbacks(void *v_reg, void *v_rx)
{
- struct pvt_rx_reg *rx_reg = v_rx;
- struct process_data *rx = v_reg;
- uint8_t ad_type;
-
- ad_type = rx->pvt->filters[rx_reg->filter_id - 1];
+ struct pvt_rx_reg *rx_reg = v_reg;
+ struct process_data *rx = v_rx;
- if (rx->data[0] == ad_type && rx_reg->cb)
+ if (!memcmp(rx->data, rx_reg->filter, rx_reg->len))
rx_reg->cb(rx_reg->user_data, &rx->info, rx->data, rx->len);
}
static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
- uint32_t instant,
+ uint32_t instant, const uint8_t *addr,
const uint8_t *data, uint8_t len)
{
struct process_data rx = {
@@ -114,6 +113,7 @@ static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
.data = data,
.len = len,
.info.instant = instant,
+ .info.addr = addr,
.info.chan = 7,
.info.rssi = rssi,
};
@@ -125,6 +125,7 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
{
const struct bt_hci_evt_le_adv_report *evt = buf;
const uint8_t *adv;
+ const uint8_t *addr;
uint32_t instant;
uint8_t adv_len;
uint16_t len = 0;
@@ -136,6 +137,7 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
instant = get_instant();
adv = evt->data;
adv_len = evt->data_len;
+ addr = evt->addr;
/* rssi is just beyond last byte of data */
rssi = (int8_t) adv[adv_len];
@@ -154,7 +156,7 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
break;
/* TODO: Create an Instant to use */
- process_rx(io->pvt, rssi, instant, adv + 1, adv[0]);
+ process_rx(io->pvt, rssi, instant, addr, adv + 1, adv[0]);
adv += field_len + 1;
}
@@ -371,7 +373,7 @@ static bool dev_caps(struct mesh_io *io, struct mesh_io_caps *caps)
if (!pvt || !caps)
return false;
- caps->max_num_filters = sizeof(pvt->filters);
+ caps->max_num_filters = 255;
caps->window_accuracy = 50;
return true;
@@ -703,12 +705,12 @@ static bool tx_cancel(struct mesh_io *io, const uint8_t *data, uint8_t len)
return true;
}
-static bool find_by_filter_id(const void *a, const void *b)
+static bool find_by_filter(const void *a, const void *b)
{
const struct pvt_rx_reg *rx_reg = a;
- uint8_t filter_id = L_PTR_TO_UINT(b);
+ const uint8_t *filter = b;
- return rx_reg->filter_id == filter_id;
+ return !memcmp(rx_reg->filter, filter, rx_reg->len);
}
static void scan_enable_rsp(const void *buf, uint8_t size,
@@ -732,28 +734,61 @@ static void set_recv_scan_enable(const void *buf, uint8_t size,
&cmd, sizeof(cmd), scan_enable_rsp, pvt, NULL);
}
-static bool recv_register(struct mesh_io *io, uint8_t filter_id,
- mesh_io_recv_func_t cb, void *user_data)
+static void scan_disable_rsp(const void *buf, uint8_t size,
+ void *user_data)
{
struct bt_hci_cmd_le_set_scan_parameters cmd;
+ struct mesh_io_private *pvt = user_data;
+ uint8_t status = *((uint8_t *) buf);
+
+ if (status)
+ l_error("LE Scan disable failed (0x%02x)", status);
+
+ cmd.type = pvt->active ? 0x01 : 0x00; /* Passive/Active scanning */
+ cmd.interval = L_CPU_TO_LE16(0x0010); /* 10 ms */
+ cmd.window = L_CPU_TO_LE16(0x0010); /* 10 ms */
+ cmd.own_addr_type = 0x01; /* ADDR_TYPE_RANDOM */
+ cmd.filter_policy = 0x00; /* Accept all */
+
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
+ &cmd, sizeof(cmd),
+ set_recv_scan_enable, pvt, NULL);
+}
+
+static bool find_active(const void *a, const void *b)
+{
+ const struct pvt_rx_reg *rx_reg = a;
+
+ /* Mesh specific AD types do *not* require active scanning,
+ * so do not turn on Active Scanning on their account.
+ */
+ if (rx_reg->filter[0] < MESH_AD_TYPE_PROVISION ||
+ rx_reg->filter[0] > MESH_AD_TYPE_BEACON)
+ return true;
+
+ return false;
+}
+
+static bool recv_register(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len, mesh_io_recv_func_t cb, void *user_data)
+{
+ struct bt_hci_cmd_le_set_scan_enable cmd;
struct mesh_io_private *pvt = io->pvt;
struct pvt_rx_reg *rx_reg;
bool already_scanning;
+ bool active = false;
- l_info("%s %d", __func__, filter_id);
- if (!cb || !filter_id || filter_id > sizeof(pvt->filters))
+ if (!cb || !filter || !len)
return false;
- rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter_id,
- L_UINT_TO_PTR(filter_id));
+ l_info("%s %2.2x", __func__, filter[0]);
+ rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
- if (!rx_reg) {
- rx_reg = l_new(struct pvt_rx_reg, 1);
- if (!rx_reg)
- return false;
- }
+ l_free(rx_reg);
+ rx_reg = l_malloc(sizeof(*rx_reg) + len);
- rx_reg->filter_id = filter_id;
+ memcpy(rx_reg->filter, filter, len);
+ rx_reg->len = len;
rx_reg->cb = cb;
rx_reg->user_data = user_data;
@@ -761,62 +796,52 @@ static bool recv_register(struct mesh_io *io, uint8_t filter_id,
l_queue_push_head(pvt->rx_regs, rx_reg);
- if (!already_scanning) {
- cmd.type = 0x00; /* Passive scanning */
- cmd.interval = L_CPU_TO_LE16(0x0010); /* 10 ms */
- cmd.window = L_CPU_TO_LE16(0x0010); /* 10 ms */
- cmd.own_addr_type = 0x01; /* ADDR_TYPE_RANDOM */
- cmd.filter_policy = 0x00; /* Accept all */
+ /* Look for any AD types requiring Active Scanning */
+ if (l_queue_find(pvt->rx_regs, find_active, NULL))
+ active = true;
+
+ if (!already_scanning || pvt->active != active) {
+ pvt->active = active;
+ cmd.enable = 0x00; /* Disable scanning */
+ cmd.filter_dup = 0x00; /* Report duplicates */
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &cmd, sizeof(cmd), scan_disable_rsp, pvt, NULL);
- bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
- &cmd, sizeof(cmd),
- set_recv_scan_enable, pvt, NULL);
}
return true;
}
-static bool recv_deregister(struct mesh_io *io, uint8_t filter_id)
+static bool recv_deregister(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len)
{
- struct bt_hci_cmd_le_set_scan_enable cmd;
+ struct bt_hci_cmd_le_set_scan_enable cmd = {0, 0};
struct mesh_io_private *pvt = io->pvt;
-
struct pvt_rx_reg *rx_reg;
+ bool active = false;
- rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter_id,
- L_UINT_TO_PTR(filter_id));
+ rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
if (rx_reg)
l_free(rx_reg);
+ /* Look for any AD types requiring Active Scanning */
+ if (l_queue_find(pvt->rx_regs, find_active, NULL))
+ active = true;
+
if (l_queue_isempty(pvt->rx_regs)) {
- cmd.enable = 0x00; /* Disable scanning */
- cmd.filter_dup = 0x00; /* Report duplicates */
bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
- &cmd, sizeof(cmd), NULL, NULL, NULL);
+ &cmd, sizeof(cmd), NULL, NULL, NULL);
+ } else if (active != pvt->active) {
+ pvt->active = active;
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &cmd, sizeof(cmd), scan_disable_rsp, pvt, NULL);
}
return true;
}
-static bool filter_set(struct mesh_io *io,
- uint8_t filter_id, const uint8_t *data, uint8_t len,
- mesh_io_status_func_t callback, void *user_data)
-{
- struct mesh_io_private *pvt = io->pvt;
-
- l_info("%s id: %d, --> %2.2x", __func__, filter_id, data[0]);
- if (!data || !len || !filter_id || filter_id > sizeof(pvt->filters))
- return false;
-
- pvt->filters[filter_id - 1] = data[0];
-
- /* TODO: Delayed Call to successful status */
-
- return true;
-}
-
const struct mesh_io_api mesh_io_generic = {
.init = dev_init,
.destroy = dev_destroy,
@@ -824,6 +849,5 @@ const struct mesh_io_api mesh_io_generic = {
.send = send_tx,
.reg = recv_register,
.dereg = recv_deregister,
- .set = filter_set,
.cancel = tx_cancel,
};
diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
index 1ab173d9c..c4eaecefd 100644
--- a/mesh/mesh-io.c
+++ b/mesh/mesh-io.c
@@ -85,18 +85,6 @@ struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
if (!io_list)
io_list = l_queue_new();
- if (api->set) {
- uint8_t pkt = MESH_AD_TYPE_NETWORK;
- uint8_t prv = MESH_AD_TYPE_PROVISION;
- uint8_t snb[2] = {MESH_AD_TYPE_BEACON, 0x01};
- uint8_t prvb[2] = {MESH_AD_TYPE_BEACON, 0x00};
-
- api->set(io, 1, snb, sizeof(snb), NULL, NULL);
- api->set(io, 2, &prv, 1, NULL, NULL);
- api->set(io, 3, &pkt, 1, NULL, NULL);
- api->set(io, 4, prvb, sizeof(prvb), NULL, NULL);
- }
-
if (l_queue_push_head(io_list, io))
return io;
@@ -133,35 +121,25 @@ bool mesh_io_get_caps(struct mesh_io *io, struct mesh_io_caps *caps)
return false;
}
-bool mesh_io_register_recv_cb(struct mesh_io *io, uint8_t filter_id,
- mesh_io_recv_func_t cb, void *user_data)
+bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len, mesh_io_recv_func_t cb,
+ void *user_data)
{
io = l_queue_find(io_list, match_by_io, io);
if (io && io->api && io->api->reg)
- return io->api->reg(io, filter_id, cb, user_data);
+ return io->api->reg(io, filter, len, cb, user_data);
return false;
}
-bool mesh_io_deregister_recv_cb(struct mesh_io *io, uint8_t filter_id)
+bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len)
{
io = l_queue_find(io_list, match_by_io, io);
if (io && io->api && io->api->dereg)
- return io->api->dereg(io, filter_id);
-
- return false;
-}
-
-bool mesh_set_filter(struct mesh_io *io, uint8_t filter_id,
- const uint8_t *data, uint8_t len,
- mesh_io_status_func_t cb, void *user_data)
-{
- io = l_queue_find(io_list, match_by_io, io);
-
- if (io && io->api && io->api->set)
- return io->api->set(io, filter_id, data, len, cb, user_data);
+ return io->api->dereg(io, filter, len);
return false;
}
diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h
index 45ff00a3c..fc0422020 100644
--- a/mesh/mesh-io.h
+++ b/mesh/mesh-io.h
@@ -19,11 +19,6 @@
struct mesh_io;
-#define MESH_IO_FILTER_BEACON 1
-#define MESH_IO_FILTER_PROV 2
-#define MESH_IO_FILTER_NET 3
-#define MESH_IO_FILTER_PROV_BEACON 4
-
#define MESH_IO_TX_COUNT_UNLIMITED 0
enum mesh_io_type {
@@ -38,6 +33,7 @@ enum mesh_io_timing_type {
};
struct mesh_io_recv_info {
+ const uint8_t *addr;
uint32_t instant;
uint8_t chan;
int8_t rssi;
@@ -78,26 +74,25 @@ typedef void (*mesh_io_recv_func_t)(void *user_data,
struct mesh_io_recv_info *info,
const uint8_t *data, uint16_t len);
-typedef void (*mesh_io_status_func_t)(void *user_data, int status,
- uint8_t filter_id);
+typedef void (*mesh_io_recv_ext_func_t)(void *user_data,
+ struct mesh_io_recv_info *info,
+ const uint8_t *data, uint16_t len,
+ const uint8_t *addr);
typedef void (*mesh_io_ready_func_t)(void *user_data, bool result);
-
struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
mesh_io_ready_func_t cb, void *user_data);
void mesh_io_destroy(struct mesh_io *io);
bool mesh_io_get_caps(struct mesh_io *io, struct mesh_io_caps *caps);
-bool mesh_io_register_recv_cb(struct mesh_io *io, uint8_t filter_id,
- mesh_io_recv_func_t cb, void *user_data);
+bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len, mesh_io_recv_func_t cb,
+ void *user_data);
-bool mesh_io_deregister_recv_cb(struct mesh_io *io, uint8_t filter_id);
-
-bool mesh_set_filter(struct mesh_io *io, uint8_t filter_id,
- const uint8_t *data, uint8_t len,
- mesh_io_status_func_t cb, void *user_data);
+bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
+ uint8_t len);
bool mesh_io_send(struct mesh_io *io, struct mesh_io_send_info *info,
const uint8_t *data, uint16_t len);
diff --git a/mesh/mesh.c b/mesh/mesh.c
index 6d2f86b6d..247c3c9be 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -141,24 +141,28 @@ static void prov_rx(void *user_data, struct mesh_io_recv_info *info,
bool mesh_reg_prov_rx(prov_rx_cb_t cb, void *user_data)
{
+ uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
+
if (mesh.prov_rx && mesh.prov_rx != cb)
return false;
mesh.prov_rx = cb;
mesh.prov_data = user_data;
- return mesh_io_register_recv_cb(mesh.io, MESH_IO_FILTER_PROV,
- prov_rx, &mesh);
+ return mesh_io_register_recv_cb(mesh.io, prov_filter,
+ sizeof(prov_filter), prov_rx, &mesh);
}
void mesh_unreg_prov_rx(prov_rx_cb_t cb)
{
+ uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
+
if (mesh.prov_rx != cb)
return;
mesh.prov_rx = NULL;
mesh.prov_data = NULL;
- mesh_io_deregister_recv_cb(mesh.io, MESH_IO_FILTER_PROV);
+ mesh_io_deregister_recv_cb(mesh.io, prov_filter, sizeof(prov_filter));
}
static void io_ready_callback(void *user_data, bool result)
diff --git a/mesh/net.c b/mesh/net.c
index ec05b6be9..5cf358fbd 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -2884,6 +2884,9 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
first = l_queue_isempty(nets);
if (first) {
+ uint8_t snb[] = {MESH_AD_TYPE_BEACON, 0x01};
+ uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
+
if (!nets)
nets = l_queue_new();
@@ -2891,9 +2894,9 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
fast_cache = l_queue_new();
l_info("Register io cb");
- mesh_io_register_recv_cb(io, MESH_IO_FILTER_BEACON,
+ mesh_io_register_recv_cb(io, snb, sizeof(snb),
beacon_recv, NULL);
- mesh_io_register_recv_cb(io, MESH_IO_FILTER_NET,
+ mesh_io_register_recv_cb(io, pkt, sizeof(pkt),
net_msg_recv, NULL);
}
@@ -2909,6 +2912,8 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
struct mesh_io *mesh_net_detach(struct mesh_net *net)
{
+ uint8_t snb[] = {MESH_AD_TYPE_BEACON, 0x01};
+ uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
struct mesh_io *io;
uint8_t type = 0;
@@ -2918,8 +2923,8 @@ struct mesh_io *mesh_net_detach(struct mesh_net *net)
io = net->io;
mesh_io_send_cancel(net->io, &type, 1);
- mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_BEACON);
- mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_NET);
+ mesh_io_deregister_recv_cb(io, snb, sizeof(snb));
+ mesh_io_deregister_recv_cb(io, pkt, sizeof(pkt));
net->io = NULL;
l_queue_remove(nets, net);
--
2.21.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH BlueZ v2] mesh: rework incoming advertisement filtering
2020-02-24 21:47 [PATCH BlueZ v2] mesh: rework incoming advertisement filtering Brian Gix
@ 2020-02-26 19:23 ` Gix, Brian
0 siblings, 0 replies; 2+ messages in thread
From: Gix, Brian @ 2020-02-26 19:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Stotland, Inga
Patch applied
On Mon, 2020-02-24 at 13:47 -0800, Brian Gix wrote:
> Future versions of Mesh will introduce new advertising packets, which
> do not fit in the limited and rigid filtering currently used. This minor
> rewrite allows registering and receiving of *any* AD types, including
> the filtering on multiple octets of the incoming AD parts.
> ---
> mesh/manager.c | 5 +-
> mesh/mesh-io-api.h | 12 ++--
> mesh/mesh-io-generic.c | 150 ++++++++++++++++++++++++-----------------
> mesh/mesh-io.c | 36 ++--------
> mesh/mesh-io.h | 25 +++----
> mesh/mesh.c | 10 ++-
> mesh/net.c | 13 ++--
> 7 files changed, 128 insertions(+), 123 deletions(-)
>
> diff --git a/mesh/manager.c b/mesh/manager.c
> index e4a7deaeb..0909c7e16 100644
> --- a/mesh/manager.c
> +++ b/mesh/manager.c
> @@ -52,6 +52,7 @@ static uint8_t scan_uuid[16];
> static struct mesh_node *scan_node;
> static struct l_timeout *scan_timeout;
> static struct add_data *add_pending;
> +static const uint8_t prvb[2] = {MESH_AD_TYPE_BEACON, 0x00};
>
> static void scan_cancel(struct l_timeout *timeout, void *user_data)
> {
> @@ -66,7 +67,7 @@ static void scan_cancel(struct l_timeout *timeout, void *user_data)
>
> net = node_get_net(node);
> io = mesh_net_get_io(net);
> - mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_PROV_BEACON);
> + mesh_io_deregister_recv_cb(io, prvb, sizeof(prvb));
> scan_node = NULL;
> scan_timeout = NULL;
> }
> @@ -397,7 +398,7 @@ static struct l_dbus_message *start_scan_call(struct l_dbus *dbus,
> net = node_get_net(node);
> io = mesh_net_get_io(net);
> scan_node = node;
> - mesh_io_register_recv_cb(io, MESH_IO_FILTER_PROV_BEACON,
> + mesh_io_register_recv_cb(io, prvb, sizeof(prvb),
> prov_beacon_recv, node);
>
> if (duration)
> diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h
> index 75b881800..7a5b49c60 100644
> --- a/mesh/mesh-io-api.h
> +++ b/mesh/mesh-io-api.h
> @@ -26,12 +26,11 @@ typedef bool (*mesh_io_caps_t)(struct mesh_io *io, struct mesh_io_caps *caps);
> typedef bool (*mesh_io_send_t)(struct mesh_io *io,
> struct mesh_io_send_info *info,
> const uint8_t *data, uint16_t len);
> -typedef bool (*mesh_io_register_t)(struct mesh_io *io, uint8_t filter_id,
> - mesh_io_recv_func_t cb, void *user_data);
> -typedef bool (*mesh_io_deregister_t)(struct mesh_io *io, uint8_t filter_id);
> -typedef bool (*mesh_io_filter_set_t)(struct mesh_io *io,
> - uint8_t filter_id, const uint8_t *data, uint8_t len,
> - mesh_io_status_func_t callback, void *user_data);
> +typedef bool (*mesh_io_register_t)(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len, mesh_io_recv_func_t cb,
> + void *user_data);
> +typedef bool (*mesh_io_deregister_t)(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len);
> typedef bool (*mesh_io_tx_cancel_t)(struct mesh_io *io, const uint8_t *pattern,
> uint8_t len);
>
> @@ -42,7 +41,6 @@ struct mesh_io_api {
> mesh_io_send_t send;
> mesh_io_register_t reg;
> mesh_io_deregister_t dereg;
> - mesh_io_filter_set_t set;
> mesh_io_tx_cancel_t cancel;
> };
>
> diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
> index b42fb4f1d..2efd32f12 100644
> --- a/mesh/mesh-io-generic.c
> +++ b/mesh/mesh-io-generic.c
> @@ -31,6 +31,7 @@
> #include "lib/bluetooth.h"
> #include "lib/mgmt.h"
>
> +#include "mesh/mesh-defs.h"
> #include "mesh/mesh-mgmt.h"
> #include "mesh/mesh-io.h"
> #include "mesh/mesh-io-api.h"
> @@ -44,16 +45,17 @@ struct mesh_io_private {
> struct l_queue *rx_regs;
> struct l_queue *tx_pkts;
> struct tx_pkt *tx;
> - uint8_t filters[4];
> - bool sending;
> uint16_t index;
> uint16_t interval;
> + bool sending;
> + bool active;
> };
>
> struct pvt_rx_reg {
> - uint8_t filter_id;
> mesh_io_recv_func_t cb;
> void *user_data;
> + uint8_t len;
> + uint8_t filter[0];
> };
>
> struct process_data {
> @@ -93,20 +95,17 @@ static uint32_t instant_remaining_ms(uint32_t instant)
> return instant;
> }
>
> -static void process_rx_callbacks(void *v_rx, void *v_reg)
> +static void process_rx_callbacks(void *v_reg, void *v_rx)
> {
> - struct pvt_rx_reg *rx_reg = v_rx;
> - struct process_data *rx = v_reg;
> - uint8_t ad_type;
> -
> - ad_type = rx->pvt->filters[rx_reg->filter_id - 1];
> + struct pvt_rx_reg *rx_reg = v_reg;
> + struct process_data *rx = v_rx;
>
> - if (rx->data[0] == ad_type && rx_reg->cb)
> + if (!memcmp(rx->data, rx_reg->filter, rx_reg->len))
> rx_reg->cb(rx_reg->user_data, &rx->info, rx->data, rx->len);
> }
>
> static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
> - uint32_t instant,
> + uint32_t instant, const uint8_t *addr,
> const uint8_t *data, uint8_t len)
> {
> struct process_data rx = {
> @@ -114,6 +113,7 @@ static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
> .data = data,
> .len = len,
> .info.instant = instant,
> + .info.addr = addr,
> .info.chan = 7,
> .info.rssi = rssi,
> };
> @@ -125,6 +125,7 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
> {
> const struct bt_hci_evt_le_adv_report *evt = buf;
> const uint8_t *adv;
> + const uint8_t *addr;
> uint32_t instant;
> uint8_t adv_len;
> uint16_t len = 0;
> @@ -136,6 +137,7 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
> instant = get_instant();
> adv = evt->data;
> adv_len = evt->data_len;
> + addr = evt->addr;
>
> /* rssi is just beyond last byte of data */
> rssi = (int8_t) adv[adv_len];
> @@ -154,7 +156,7 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
> break;
>
> /* TODO: Create an Instant to use */
> - process_rx(io->pvt, rssi, instant, adv + 1, adv[0]);
> + process_rx(io->pvt, rssi, instant, addr, adv + 1, adv[0]);
>
> adv += field_len + 1;
> }
> @@ -371,7 +373,7 @@ static bool dev_caps(struct mesh_io *io, struct mesh_io_caps *caps)
> if (!pvt || !caps)
> return false;
>
> - caps->max_num_filters = sizeof(pvt->filters);
> + caps->max_num_filters = 255;
> caps->window_accuracy = 50;
>
> return true;
> @@ -703,12 +705,12 @@ static bool tx_cancel(struct mesh_io *io, const uint8_t *data, uint8_t len)
> return true;
> }
>
> -static bool find_by_filter_id(const void *a, const void *b)
> +static bool find_by_filter(const void *a, const void *b)
> {
> const struct pvt_rx_reg *rx_reg = a;
> - uint8_t filter_id = L_PTR_TO_UINT(b);
> + const uint8_t *filter = b;
>
> - return rx_reg->filter_id == filter_id;
> + return !memcmp(rx_reg->filter, filter, rx_reg->len);
> }
>
> static void scan_enable_rsp(const void *buf, uint8_t size,
> @@ -732,28 +734,61 @@ static void set_recv_scan_enable(const void *buf, uint8_t size,
> &cmd, sizeof(cmd), scan_enable_rsp, pvt, NULL);
> }
>
> -static bool recv_register(struct mesh_io *io, uint8_t filter_id,
> - mesh_io_recv_func_t cb, void *user_data)
> +static void scan_disable_rsp(const void *buf, uint8_t size,
> + void *user_data)
> {
> struct bt_hci_cmd_le_set_scan_parameters cmd;
> + struct mesh_io_private *pvt = user_data;
> + uint8_t status = *((uint8_t *) buf);
> +
> + if (status)
> + l_error("LE Scan disable failed (0x%02x)", status);
> +
> + cmd.type = pvt->active ? 0x01 : 0x00; /* Passive/Active scanning */
> + cmd.interval = L_CPU_TO_LE16(0x0010); /* 10 ms */
> + cmd.window = L_CPU_TO_LE16(0x0010); /* 10 ms */
> + cmd.own_addr_type = 0x01; /* ADDR_TYPE_RANDOM */
> + cmd.filter_policy = 0x00; /* Accept all */
> +
> + bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
> + &cmd, sizeof(cmd),
> + set_recv_scan_enable, pvt, NULL);
> +}
> +
> +static bool find_active(const void *a, const void *b)
> +{
> + const struct pvt_rx_reg *rx_reg = a;
> +
> + /* Mesh specific AD types do *not* require active scanning,
> + * so do not turn on Active Scanning on their account.
> + */
> + if (rx_reg->filter[0] < MESH_AD_TYPE_PROVISION ||
> + rx_reg->filter[0] > MESH_AD_TYPE_BEACON)
> + return true;
> +
> + return false;
> +}
> +
> +static bool recv_register(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len, mesh_io_recv_func_t cb, void *user_data)
> +{
> + struct bt_hci_cmd_le_set_scan_enable cmd;
> struct mesh_io_private *pvt = io->pvt;
> struct pvt_rx_reg *rx_reg;
> bool already_scanning;
> + bool active = false;
>
> - l_info("%s %d", __func__, filter_id);
> - if (!cb || !filter_id || filter_id > sizeof(pvt->filters))
> + if (!cb || !filter || !len)
> return false;
>
> - rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter_id,
> - L_UINT_TO_PTR(filter_id));
> + l_info("%s %2.2x", __func__, filter[0]);
> + rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
>
> - if (!rx_reg) {
> - rx_reg = l_new(struct pvt_rx_reg, 1);
> - if (!rx_reg)
> - return false;
> - }
> + l_free(rx_reg);
> + rx_reg = l_malloc(sizeof(*rx_reg) + len);
>
> - rx_reg->filter_id = filter_id;
> + memcpy(rx_reg->filter, filter, len);
> + rx_reg->len = len;
> rx_reg->cb = cb;
> rx_reg->user_data = user_data;
>
> @@ -761,62 +796,52 @@ static bool recv_register(struct mesh_io *io, uint8_t filter_id,
>
> l_queue_push_head(pvt->rx_regs, rx_reg);
>
> - if (!already_scanning) {
> - cmd.type = 0x00; /* Passive scanning */
> - cmd.interval = L_CPU_TO_LE16(0x0010); /* 10 ms */
> - cmd.window = L_CPU_TO_LE16(0x0010); /* 10 ms */
> - cmd.own_addr_type = 0x01; /* ADDR_TYPE_RANDOM */
> - cmd.filter_policy = 0x00; /* Accept all */
> + /* Look for any AD types requiring Active Scanning */
> + if (l_queue_find(pvt->rx_regs, find_active, NULL))
> + active = true;
> +
> + if (!already_scanning || pvt->active != active) {
> + pvt->active = active;
> + cmd.enable = 0x00; /* Disable scanning */
> + cmd.filter_dup = 0x00; /* Report duplicates */
> + bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
> + &cmd, sizeof(cmd), scan_disable_rsp, pvt, NULL);
>
> - bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
> - &cmd, sizeof(cmd),
> - set_recv_scan_enable, pvt, NULL);
> }
>
> return true;
> }
>
> -static bool recv_deregister(struct mesh_io *io, uint8_t filter_id)
> +static bool recv_deregister(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len)
> {
> - struct bt_hci_cmd_le_set_scan_enable cmd;
> + struct bt_hci_cmd_le_set_scan_enable cmd = {0, 0};
> struct mesh_io_private *pvt = io->pvt;
> -
> struct pvt_rx_reg *rx_reg;
> + bool active = false;
>
> - rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter_id,
> - L_UINT_TO_PTR(filter_id));
> + rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
>
> if (rx_reg)
> l_free(rx_reg);
>
> + /* Look for any AD types requiring Active Scanning */
> + if (l_queue_find(pvt->rx_regs, find_active, NULL))
> + active = true;
> +
> if (l_queue_isempty(pvt->rx_regs)) {
> - cmd.enable = 0x00; /* Disable scanning */
> - cmd.filter_dup = 0x00; /* Report duplicates */
> bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
> - &cmd, sizeof(cmd), NULL, NULL, NULL);
> + &cmd, sizeof(cmd), NULL, NULL, NULL);
>
> + } else if (active != pvt->active) {
> + pvt->active = active;
> + bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
> + &cmd, sizeof(cmd), scan_disable_rsp, pvt, NULL);
> }
>
> return true;
> }
>
> -static bool filter_set(struct mesh_io *io,
> - uint8_t filter_id, const uint8_t *data, uint8_t len,
> - mesh_io_status_func_t callback, void *user_data)
> -{
> - struct mesh_io_private *pvt = io->pvt;
> -
> - l_info("%s id: %d, --> %2.2x", __func__, filter_id, data[0]);
> - if (!data || !len || !filter_id || filter_id > sizeof(pvt->filters))
> - return false;
> -
> - pvt->filters[filter_id - 1] = data[0];
> -
> - /* TODO: Delayed Call to successful status */
> -
> - return true;
> -}
> -
> const struct mesh_io_api mesh_io_generic = {
> .init = dev_init,
> .destroy = dev_destroy,
> @@ -824,6 +849,5 @@ const struct mesh_io_api mesh_io_generic = {
> .send = send_tx,
> .reg = recv_register,
> .dereg = recv_deregister,
> - .set = filter_set,
> .cancel = tx_cancel,
> };
> diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
> index 1ab173d9c..c4eaecefd 100644
> --- a/mesh/mesh-io.c
> +++ b/mesh/mesh-io.c
> @@ -85,18 +85,6 @@ struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
> if (!io_list)
> io_list = l_queue_new();
>
> - if (api->set) {
> - uint8_t pkt = MESH_AD_TYPE_NETWORK;
> - uint8_t prv = MESH_AD_TYPE_PROVISION;
> - uint8_t snb[2] = {MESH_AD_TYPE_BEACON, 0x01};
> - uint8_t prvb[2] = {MESH_AD_TYPE_BEACON, 0x00};
> -
> - api->set(io, 1, snb, sizeof(snb), NULL, NULL);
> - api->set(io, 2, &prv, 1, NULL, NULL);
> - api->set(io, 3, &pkt, 1, NULL, NULL);
> - api->set(io, 4, prvb, sizeof(prvb), NULL, NULL);
> - }
> -
> if (l_queue_push_head(io_list, io))
> return io;
>
> @@ -133,35 +121,25 @@ bool mesh_io_get_caps(struct mesh_io *io, struct mesh_io_caps *caps)
> return false;
> }
>
> -bool mesh_io_register_recv_cb(struct mesh_io *io, uint8_t filter_id,
> - mesh_io_recv_func_t cb, void *user_data)
> +bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len, mesh_io_recv_func_t cb,
> + void *user_data)
> {
> io = l_queue_find(io_list, match_by_io, io);
>
> if (io && io->api && io->api->reg)
> - return io->api->reg(io, filter_id, cb, user_data);
> + return io->api->reg(io, filter, len, cb, user_data);
>
> return false;
> }
>
> -bool mesh_io_deregister_recv_cb(struct mesh_io *io, uint8_t filter_id)
> +bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len)
> {
> io = l_queue_find(io_list, match_by_io, io);
>
> if (io && io->api && io->api->dereg)
> - return io->api->dereg(io, filter_id);
> -
> - return false;
> -}
> -
> -bool mesh_set_filter(struct mesh_io *io, uint8_t filter_id,
> - const uint8_t *data, uint8_t len,
> - mesh_io_status_func_t cb, void *user_data)
> -{
> - io = l_queue_find(io_list, match_by_io, io);
> -
> - if (io && io->api && io->api->set)
> - return io->api->set(io, filter_id, data, len, cb, user_data);
> + return io->api->dereg(io, filter, len);
>
> return false;
> }
> diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h
> index 45ff00a3c..fc0422020 100644
> --- a/mesh/mesh-io.h
> +++ b/mesh/mesh-io.h
> @@ -19,11 +19,6 @@
>
> struct mesh_io;
>
> -#define MESH_IO_FILTER_BEACON 1
> -#define MESH_IO_FILTER_PROV 2
> -#define MESH_IO_FILTER_NET 3
> -#define MESH_IO_FILTER_PROV_BEACON 4
> -
> #define MESH_IO_TX_COUNT_UNLIMITED 0
>
> enum mesh_io_type {
> @@ -38,6 +33,7 @@ enum mesh_io_timing_type {
> };
>
> struct mesh_io_recv_info {
> + const uint8_t *addr;
> uint32_t instant;
> uint8_t chan;
> int8_t rssi;
> @@ -78,26 +74,25 @@ typedef void (*mesh_io_recv_func_t)(void *user_data,
> struct mesh_io_recv_info *info,
> const uint8_t *data, uint16_t len);
>
> -typedef void (*mesh_io_status_func_t)(void *user_data, int status,
> - uint8_t filter_id);
> +typedef void (*mesh_io_recv_ext_func_t)(void *user_data,
> + struct mesh_io_recv_info *info,
> + const uint8_t *data, uint16_t len,
> + const uint8_t *addr);
>
> typedef void (*mesh_io_ready_func_t)(void *user_data, bool result);
>
> -
> struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
> mesh_io_ready_func_t cb, void *user_data);
> void mesh_io_destroy(struct mesh_io *io);
>
> bool mesh_io_get_caps(struct mesh_io *io, struct mesh_io_caps *caps);
>
> -bool mesh_io_register_recv_cb(struct mesh_io *io, uint8_t filter_id,
> - mesh_io_recv_func_t cb, void *user_data);
> +bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len, mesh_io_recv_func_t cb,
> + void *user_data);
>
> -bool mesh_io_deregister_recv_cb(struct mesh_io *io, uint8_t filter_id);
> -
> -bool mesh_set_filter(struct mesh_io *io, uint8_t filter_id,
> - const uint8_t *data, uint8_t len,
> - mesh_io_status_func_t cb, void *user_data);
> +bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
> + uint8_t len);
>
> bool mesh_io_send(struct mesh_io *io, struct mesh_io_send_info *info,
> const uint8_t *data, uint16_t len);
> diff --git a/mesh/mesh.c b/mesh/mesh.c
> index 6d2f86b6d..247c3c9be 100644
> --- a/mesh/mesh.c
> +++ b/mesh/mesh.c
> @@ -141,24 +141,28 @@ static void prov_rx(void *user_data, struct mesh_io_recv_info *info,
>
> bool mesh_reg_prov_rx(prov_rx_cb_t cb, void *user_data)
> {
> + uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
> +
> if (mesh.prov_rx && mesh.prov_rx != cb)
> return false;
>
> mesh.prov_rx = cb;
> mesh.prov_data = user_data;
>
> - return mesh_io_register_recv_cb(mesh.io, MESH_IO_FILTER_PROV,
> - prov_rx, &mesh);
> + return mesh_io_register_recv_cb(mesh.io, prov_filter,
> + sizeof(prov_filter), prov_rx, &mesh);
> }
>
> void mesh_unreg_prov_rx(prov_rx_cb_t cb)
> {
> + uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
> +
> if (mesh.prov_rx != cb)
> return;
>
> mesh.prov_rx = NULL;
> mesh.prov_data = NULL;
> - mesh_io_deregister_recv_cb(mesh.io, MESH_IO_FILTER_PROV);
> + mesh_io_deregister_recv_cb(mesh.io, prov_filter, sizeof(prov_filter));
> }
>
> static void io_ready_callback(void *user_data, bool result)
> diff --git a/mesh/net.c b/mesh/net.c
> index ec05b6be9..5cf358fbd 100644
> --- a/mesh/net.c
> +++ b/mesh/net.c
> @@ -2884,6 +2884,9 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
>
> first = l_queue_isempty(nets);
> if (first) {
> + uint8_t snb[] = {MESH_AD_TYPE_BEACON, 0x01};
> + uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
> +
> if (!nets)
> nets = l_queue_new();
>
> @@ -2891,9 +2894,9 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
> fast_cache = l_queue_new();
>
> l_info("Register io cb");
> - mesh_io_register_recv_cb(io, MESH_IO_FILTER_BEACON,
> + mesh_io_register_recv_cb(io, snb, sizeof(snb),
> beacon_recv, NULL);
> - mesh_io_register_recv_cb(io, MESH_IO_FILTER_NET,
> + mesh_io_register_recv_cb(io, pkt, sizeof(pkt),
> net_msg_recv, NULL);
> }
>
> @@ -2909,6 +2912,8 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
>
> struct mesh_io *mesh_net_detach(struct mesh_net *net)
> {
> + uint8_t snb[] = {MESH_AD_TYPE_BEACON, 0x01};
> + uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
> struct mesh_io *io;
> uint8_t type = 0;
>
> @@ -2918,8 +2923,8 @@ struct mesh_io *mesh_net_detach(struct mesh_net *net)
> io = net->io;
>
> mesh_io_send_cancel(net->io, &type, 1);
> - mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_BEACON);
> - mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_NET);
> + mesh_io_deregister_recv_cb(io, snb, sizeof(snb));
> + mesh_io_deregister_recv_cb(io, pkt, sizeof(pkt));
>
> net->io = NULL;
> l_queue_remove(nets, net);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-02-26 19:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-24 21:47 [PATCH BlueZ v2] mesh: rework incoming advertisement filtering Brian Gix
2020-02-26 19:23 ` Gix, Brian
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).