mesh: rework incoming advertisement filtering 39/228939/1
authorBrian Gix <brian.gix@intel.com>
Sun, 23 Feb 2020 18:47:37 +0000 (10:47 -0800)
committerAnupam Roy <anupam.r@samsung.com>
Thu, 26 Mar 2020 10:27:53 +0000 (15:57 +0530)
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.

Change-Id: I36c8f673100afbfd3738d9e243020f13064c7262
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
mesh/manager.c
mesh/mesh-io-api.h
mesh/mesh-io-generic.c
mesh/mesh-io.c
mesh/mesh-io.h
mesh/mesh.c
mesh/net.c

index 9f539ab..90b8785 100644 (file)
@@ -54,6 +54,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)
 {
@@ -68,7 +69,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;
 }
@@ -399,7 +400,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)
index 75b8818..7a5b49c 100644 (file)
@@ -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;
 };
 
index b42fb4f..2efd32f 100644 (file)
@@ -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,
 };
index 1ab173d..c4eaece 100644 (file)
@@ -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;
 }
index 45ff00a..fc04220 100644 (file)
 
 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);
index 0e02502..4993a67 100644 (file)
@@ -140,24 +140,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)
index 493a867..8bf4c8c 100644 (file)
@@ -2882,6 +2882,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();
 
@@ -2889,9 +2892,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);
        }
 
@@ -2907,6 +2910,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;
 
@@ -2916,8 +2921,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);