6lowpan: Use netdev addr_len to determine lladdr len

This allow technologies such as Bluetooth to use its native lladdr which
is eui48 instead of eui64 which was expected by functions like
lowpan_header_decompress and lowpan_header_compress.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Luiz Augusto von Dentz
2017-03-12 10:19:37 +02:00
committed by Marcel Holtmann
parent 8a7a4b4767
commit fa09ae661f
3 changed files with 63 additions and 47 deletions

View File

@@ -278,6 +278,23 @@ lowpan_iphc_ctx_get_by_mcast_addr(const struct net_device *dev,
return ret;
}
static void lowpan_iphc_uncompress_lladdr(const struct net_device *dev,
struct in6_addr *ipaddr,
const void *lladdr)
{
switch (dev->addr_len) {
case ETH_ALEN:
lowpan_iphc_uncompress_eui48_lladdr(ipaddr, lladdr);
break;
case EUI64_ADDR_LEN:
lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
break;
default:
WARN_ON_ONCE(1);
break;
}
}
/* Uncompress address function for source and
* destination address(non-multicast).
*
@@ -320,7 +337,7 @@ static int lowpan_iphc_uncompress_addr(struct sk_buff *skb,
lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr);
break;
default:
lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
lowpan_iphc_uncompress_lladdr(dev, ipaddr, lladdr);
break;
}
break;
@@ -381,7 +398,7 @@ static int lowpan_iphc_uncompress_ctx_addr(struct sk_buff *skb,
lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr);
break;
default:
lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
lowpan_iphc_uncompress_lladdr(dev, ipaddr, lladdr);
break;
}
ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
@@ -810,6 +827,21 @@ lowpan_iphc_compress_ctx_802154_lladdr(const struct in6_addr *ipaddr,
return lladdr_compress;
}
static bool lowpan_iphc_addr_equal(const struct net_device *dev,
const struct lowpan_iphc_ctx *ctx,
const struct in6_addr *ipaddr,
const void *lladdr)
{
struct in6_addr tmp = {};
lowpan_iphc_uncompress_lladdr(dev, &tmp, lladdr);
if (ctx)
ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
return ipv6_addr_equal(&tmp, ipaddr);
}
static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct net_device *dev,
const struct in6_addr *ipaddr,
const struct lowpan_iphc_ctx *ctx,
@@ -827,13 +859,7 @@ static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct net_device *dev,
}
break;
default:
/* check for SAM/DAM = 11 */
memcpy(&tmp.s6_addr[8], lladdr, EUI64_ADDR_LEN);
/* second bit-flip (Universe/Local) is done according RFC2464 */
tmp.s6_addr[8] ^= 0x02;
/* context information are always used */
ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
if (ipv6_addr_equal(&tmp, ipaddr)) {
if (lowpan_iphc_addr_equal(dev, ctx, ipaddr, lladdr)) {
dam = LOWPAN_IPHC_DAM_11;
goto out;
}
@@ -929,11 +955,12 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, const struct net_device *dev,
}
break;
default:
if (is_addr_mac_addr_based(ipaddr, lladdr)) {
dam = LOWPAN_IPHC_DAM_11; /* 0-bits */
if (lowpan_iphc_addr_equal(dev, NULL, ipaddr, lladdr)) {
dam = LOWPAN_IPHC_DAM_11;
pr_debug("address compression 0 bits\n");
goto out;
}
break;
}