Like any IPv6 capable device, 6LNs can have multiple addresses assigned using SLAAC and made known through neighbour advertisements. After checking the destination address against all peers link-local addresses, consult the neighbour cache for additional known addresses. RFC7668 defines the scope of Neighbor Advertisements in Section 3.2.3: 1. "A Bluetooth LE 6LN MUST NOT register its link-local address" 2. "A Bluetooth LE 6LN MUST register its non-link-local addresses with the 6LBR by sending Neighbor Solicitation (NS) messages ..." Due to these constranits both the link-local addresses tracked in the list of 6lowpan peers, and the neighbour cache have to be used when identifying the 6lowpan peer for a destination address. Acked-by: Jukka Rissanen <jukka.rissanen@xxxxxxxxxxxxxxx> Tested-by: Michael Scott <mike@xxxxxxxxxxxx> Signed-off-by: Josua Mayer <josua.mayer@xxxxxx> --- net/bluetooth/6lowpan.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 50530561da98..29a4f3d65348 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -171,6 +171,7 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev, struct in6_addr *nexthop; struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); int count = atomic_read(&dev->peer_count); + struct neighbour *neigh; BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt); @@ -222,6 +223,20 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev, } } + /* use the neighbour cache for matching addresses assigned by SLAAC + */ + neigh = __ipv6_neigh_lookup(dev->netdev, nexthop); + if (neigh) { + list_for_each_entry_rcu(peer, &dev->peers, list) { + if (!memcmp(neigh->ha, peer->lladdr, ETH_ALEN)) { + neigh_release(neigh); + rcu_read_unlock(); + return peer; + } + } + neigh_release(neigh); + } + rcu_read_unlock(); return NULL; -- 2.21.0