* [PATCH v10 3/5] ipv6: Add checks for 6LOWPAN ARP type
From: Jukka Rissanen @ 2013-12-11 15:05 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386774338-2093-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Acked-by: David S. Miller <davem@davemloft.net>
---
net/ipv6/addrconf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 12c97d8..d125fcd 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1816,6 +1816,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
return addrconf_ifid_sit(eui, dev);
case ARPHRD_IPGRE:
return addrconf_ifid_gre(eui, dev);
+ case ARPHRD_6LOWPAN:
case ARPHRD_IEEE802154:
return addrconf_ifid_eui64(eui, dev);
case ARPHRD_IEEE1394:
@@ -2658,7 +2659,8 @@ static void addrconf_dev_config(struct net_device *dev)
(dev->type != ARPHRD_INFINIBAND) &&
(dev->type != ARPHRD_IEEE802154) &&
(dev->type != ARPHRD_IEEE1394) &&
- (dev->type != ARPHRD_TUNNEL6)) {
+ (dev->type != ARPHRD_TUNNEL6) &&
+ (dev->type != ARPHRD_6LOWPAN)) {
/* Alas, we support only Ethernet autoconfiguration. */
return;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v10 2/5] net: if_arp: add ARPHRD_6LOWPAN type
From: Jukka Rissanen @ 2013-12-11 15:05 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386774338-2093-1-git-send-email-jukka.rissanen@linux.intel.com>
Used for IPv6 over LoWPAN networks. Example of this is
Bluetooth 6LoWPAN network.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Acked-by: David S. Miller <davem@davemloft.net>
---
include/uapi/linux/if_arp.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h
index d7fea34..4d024d7 100644
--- a/include/uapi/linux/if_arp.h
+++ b/include/uapi/linux/if_arp.h
@@ -94,6 +94,7 @@
#define ARPHRD_CAIF 822 /* CAIF media type */
#define ARPHRD_IP6GRE 823 /* GRE over IPv6 */
#define ARPHRD_NETLINK 824 /* Netlink header */
+#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
#define ARPHRD_NONE 0xFFFE /* zero header length */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v10 1/5] 6lowpan: Moving generic compression code into 6lowpan_iphc.c
From: Jukka Rissanen @ 2013-12-11 15:05 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386774338-2093-1-git-send-email-jukka.rissanen@linux.intel.com>
Because the IEEE 802154 and Bluetooth share the IP header compression
and uncompression code, the common code is moved to 6lowpan_iphc.c
file.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Acked-by: Alexander Aring <alex.aring@gmail.com>
---
net/ieee802154/6lowpan.c | 753 ++-------------------------------------
net/ieee802154/6lowpan.h | 32 ++
net/ieee802154/6lowpan_iphc.c | 807 ++++++++++++++++++++++++++++++++++++++++++
net/ieee802154/Makefile | 2 +-
4 files changed, 875 insertions(+), 719 deletions(-)
create mode 100644 net/ieee802154/6lowpan_iphc.c
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 459e200..53d0bd5 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -62,9 +62,6 @@
#include "6lowpan.h"
-/* TTL uncompression values */
-static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
-
static LIST_HEAD(lowpan_devices);
/* private device info */
@@ -135,347 +132,14 @@ static inline void lowpan_raw_dump_table(const char *caller, char *msg,
#endif /* DEBUG */
}
-static u8
-lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
- const unsigned char *lladdr)
-{
- u8 val = 0;
-
- if (is_addr_mac_addr_based(ipaddr, lladdr))
- val = 3; /* 0-bits */
- else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
- /* compress IID to 16 bits xxxx::XXXX */
- memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
- *hc06_ptr += 2;
- val = 2; /* 16-bits */
- } else {
- /* do not compress IID => xxxx::IID */
- memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
- *hc06_ptr += 8;
- val = 1; /* 64-bits */
- }
-
- return rol8(val, shift);
-}
-
-/*
- * Uncompress address function for source and
- * destination address(non-multicast).
- *
- * address_mode is sam value or dam value.
- */
-static int
-lowpan_uncompress_addr(struct sk_buff *skb,
- struct in6_addr *ipaddr,
- const u8 address_mode,
- const struct ieee802154_addr *lladdr)
-{
- bool fail;
-
- switch (address_mode) {
- case LOWPAN_IPHC_ADDR_00:
- /* for global link addresses */
- fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
- break;
- case LOWPAN_IPHC_ADDR_01:
- /* fe:80::XXXX:XXXX:XXXX:XXXX */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
- break;
- case LOWPAN_IPHC_ADDR_02:
- /* fe:80::ff:fe00:XXXX */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- ipaddr->s6_addr[11] = 0xFF;
- ipaddr->s6_addr[12] = 0xFE;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
- break;
- case LOWPAN_IPHC_ADDR_03:
- fail = false;
- switch (lladdr->addr_type) {
- case IEEE802154_ADDR_LONG:
- /* fe:80::XXXX:XXXX:XXXX:XXXX
- * \_________________/
- * hwaddr
- */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr,
- IEEE802154_ADDR_LEN);
- /* second bit-flip (Universe/Local)
- * is done according RFC2464
- */
- ipaddr->s6_addr[8] ^= 0x02;
- break;
- case IEEE802154_ADDR_SHORT:
- /* fe:80::ff:fe00:XXXX
- * \__/
- * short_addr
- *
- * Universe/Local bit is zero.
- */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- ipaddr->s6_addr[11] = 0xFF;
- ipaddr->s6_addr[12] = 0xFE;
- ipaddr->s6_addr16[7] = htons(lladdr->short_addr);
- break;
- default:
- pr_debug("Invalid addr_type set\n");
- return -EINVAL;
- }
- break;
- default:
- pr_debug("Invalid address mode value: 0x%x\n", address_mode);
- return -EINVAL;
- }
-
- if (fail) {
- pr_debug("Failed to fetch skb data\n");
- return -EIO;
- }
-
- lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 addr is:\n",
- ipaddr->s6_addr, 16);
-
- return 0;
-}
-
-/* Uncompress address function for source context
- * based address(non-multicast).
- */
-static int
-lowpan_uncompress_context_based_src_addr(struct sk_buff *skb,
- struct in6_addr *ipaddr,
- const u8 sam)
-{
- switch (sam) {
- case LOWPAN_IPHC_ADDR_00:
- /* unspec address ::
- * Do nothing, address is already ::
- */
- break;
- case LOWPAN_IPHC_ADDR_01:
- /* TODO */
- case LOWPAN_IPHC_ADDR_02:
- /* TODO */
- case LOWPAN_IPHC_ADDR_03:
- /* TODO */
- netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
- return -EINVAL;
- default:
- pr_debug("Invalid sam value: 0x%x\n", sam);
- return -EINVAL;
- }
-
- lowpan_raw_dump_inline(NULL,
- "Reconstructed context based ipv6 src addr is:\n",
- ipaddr->s6_addr, 16);
-
- return 0;
-}
-
-/* Uncompress function for multicast destination address,
- * when M bit is set.
- */
-static int
-lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
- struct in6_addr *ipaddr,
- const u8 dam)
-{
- bool fail;
-
- switch (dam) {
- case LOWPAN_IPHC_DAM_00:
- /* 00: 128 bits. The full address
- * is carried in-line.
- */
- fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
- break;
- case LOWPAN_IPHC_DAM_01:
- /* 01: 48 bits. The address takes
- * the form ffXX::00XX:XXXX:XXXX.
- */
- ipaddr->s6_addr[0] = 0xFF;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
- fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
- break;
- case LOWPAN_IPHC_DAM_10:
- /* 10: 32 bits. The address takes
- * the form ffXX::00XX:XXXX.
- */
- ipaddr->s6_addr[0] = 0xFF;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
- fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
- break;
- case LOWPAN_IPHC_DAM_11:
- /* 11: 8 bits. The address takes
- * the form ff02::00XX.
- */
- ipaddr->s6_addr[0] = 0xFF;
- ipaddr->s6_addr[1] = 0x02;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
- break;
- default:
- pr_debug("DAM value has a wrong value: 0x%x\n", dam);
- return -EINVAL;
- }
-
- if (fail) {
- pr_debug("Failed to fetch skb data\n");
- return -EIO;
- }
-
- lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n",
- ipaddr->s6_addr, 16);
-
- return 0;
-}
-
-static void
-lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
-{
- struct udphdr *uh = udp_hdr(skb);
-
- if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
- LOWPAN_NHC_UDP_4BIT_PORT) &&
- ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
- LOWPAN_NHC_UDP_4BIT_PORT)) {
- pr_debug("UDP header: both ports compression to 4 bits\n");
- **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
- **(hc06_ptr + 1) = /* subtraction is faster */
- (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
- ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
- *hc06_ptr += 2;
- } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
- LOWPAN_NHC_UDP_8BIT_PORT) {
- pr_debug("UDP header: remove 8 bits of dest\n");
- **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
- memcpy(*hc06_ptr + 1, &uh->source, 2);
- **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
- *hc06_ptr += 4;
- } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
- LOWPAN_NHC_UDP_8BIT_PORT) {
- pr_debug("UDP header: remove 8 bits of source\n");
- **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
- memcpy(*hc06_ptr + 1, &uh->dest, 2);
- **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
- *hc06_ptr += 4;
- } else {
- pr_debug("UDP header: can't compress\n");
- **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
- memcpy(*hc06_ptr + 1, &uh->source, 2);
- memcpy(*hc06_ptr + 3, &uh->dest, 2);
- *hc06_ptr += 5;
- }
-
- /* checksum is always inline */
- memcpy(*hc06_ptr, &uh->check, 2);
- *hc06_ptr += 2;
-
- /* skip the UDP header */
- skb_pull(skb, sizeof(struct udphdr));
-}
-
-static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
-{
- if (unlikely(!pskb_may_pull(skb, 1)))
- return -EINVAL;
-
- *val = skb->data[0];
- skb_pull(skb, 1);
-
- return 0;
-}
-
-static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
-{
- if (unlikely(!pskb_may_pull(skb, 2)))
- return -EINVAL;
-
- *val = (skb->data[0] << 8) | skb->data[1];
- skb_pull(skb, 2);
-
- return 0;
-}
-
-static int
-lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
-{
- u8 tmp;
-
- if (!uh)
- goto err;
-
- if (lowpan_fetch_skb_u8(skb, &tmp))
- goto err;
-
- if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
- pr_debug("UDP header uncompression\n");
- switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
- case LOWPAN_NHC_UDP_CS_P_00:
- memcpy(&uh->source, &skb->data[0], 2);
- memcpy(&uh->dest, &skb->data[2], 2);
- skb_pull(skb, 4);
- break;
- case LOWPAN_NHC_UDP_CS_P_01:
- memcpy(&uh->source, &skb->data[0], 2);
- uh->dest =
- skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT;
- skb_pull(skb, 3);
- break;
- case LOWPAN_NHC_UDP_CS_P_10:
- uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT;
- memcpy(&uh->dest, &skb->data[1], 2);
- skb_pull(skb, 3);
- break;
- case LOWPAN_NHC_UDP_CS_P_11:
- uh->source =
- LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4);
- uh->dest =
- LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f);
- skb_pull(skb, 1);
- break;
- default:
- pr_debug("ERROR: unknown UDP format\n");
- goto err;
- }
-
- pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
- uh->source, uh->dest);
-
- /* copy checksum */
- memcpy(&uh->check, &skb->data[0], 2);
- skb_pull(skb, 2);
-
- /*
- * UDP lenght needs to be infered from the lower layers
- * here, we obtain the hint from the remaining size of the
- * frame
- */
- uh->len = htons(skb->len + sizeof(struct udphdr));
- pr_debug("uncompressed UDP length: src = %d", uh->len);
- } else {
- pr_debug("ERROR: unsupported NH format\n");
- goto err;
- }
-
- return 0;
-err:
- return -EINVAL;
-}
-
static int lowpan_header_create(struct sk_buff *skb,
struct net_device *dev,
unsigned short type, const void *_daddr,
const void *_saddr, unsigned int len)
{
- u8 tmp, iphc0, iphc1, *hc06_ptr;
struct ipv6hdr *hdr;
const u8 *saddr = _saddr;
const u8 *daddr = _daddr;
- u8 head[100];
struct ieee802154_addr sa, da;
/* TODO:
@@ -485,181 +149,14 @@ static int lowpan_header_create(struct sk_buff *skb,
return 0;
hdr = ipv6_hdr(skb);
- hc06_ptr = head + 2;
-
- pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
- "\tnexthdr = 0x%02x\n\thop_lim = %d\n", hdr->version,
- ntohs(hdr->payload_len), hdr->nexthdr, hdr->hop_limit);
-
- lowpan_raw_dump_table(__func__, "raw skb network header dump",
- skb_network_header(skb), sizeof(struct ipv6hdr));
if (!saddr)
saddr = dev->dev_addr;
lowpan_raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
-
- /*
- * As we copy some bit-length fields, in the IPHC encoding bytes,
- * we sometimes use |=
- * If the field is 0, and the current bit value in memory is 1,
- * this does not work. We therefore reset the IPHC encoding here
- */
- iphc0 = LOWPAN_DISPATCH_IPHC;
- iphc1 = 0;
-
- /* TODO: context lookup */
-
lowpan_raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
- /*
- * Traffic class, flow label
- * If flow label is 0, compress it. If traffic class is 0, compress it
- * We have to process both in the same time as the offset of traffic
- * class depends on the presence of version and flow label
- */
-
- /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
- tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
- tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
-
- if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
- (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
- /* flow label can be compressed */
- iphc0 |= LOWPAN_IPHC_FL_C;
- if ((hdr->priority == 0) &&
- ((hdr->flow_lbl[0] & 0xF0) == 0)) {
- /* compress (elide) all */
- iphc0 |= LOWPAN_IPHC_TC_C;
- } else {
- /* compress only the flow label */
- *hc06_ptr = tmp;
- hc06_ptr += 1;
- }
- } else {
- /* Flow label cannot be compressed */
- if ((hdr->priority == 0) &&
- ((hdr->flow_lbl[0] & 0xF0) == 0)) {
- /* compress only traffic class */
- iphc0 |= LOWPAN_IPHC_TC_C;
- *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
- memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
- hc06_ptr += 3;
- } else {
- /* compress nothing */
- memcpy(hc06_ptr, &hdr, 4);
- /* replace the top byte with new ECN | DSCP format */
- *hc06_ptr = tmp;
- hc06_ptr += 4;
- }
- }
-
- /* NOTE: payload length is always compressed */
-
- /* Next Header is compress if UDP */
- if (hdr->nexthdr == UIP_PROTO_UDP)
- iphc0 |= LOWPAN_IPHC_NH_C;
-
- if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
- *hc06_ptr = hdr->nexthdr;
- hc06_ptr += 1;
- }
-
- /*
- * Hop limit
- * if 1: compress, encoding is 01
- * if 64: compress, encoding is 10
- * if 255: compress, encoding is 11
- * else do not compress
- */
- switch (hdr->hop_limit) {
- case 1:
- iphc0 |= LOWPAN_IPHC_TTL_1;
- break;
- case 64:
- iphc0 |= LOWPAN_IPHC_TTL_64;
- break;
- case 255:
- iphc0 |= LOWPAN_IPHC_TTL_255;
- break;
- default:
- *hc06_ptr = hdr->hop_limit;
- hc06_ptr += 1;
- break;
- }
-
- /* source address compression */
- if (is_addr_unspecified(&hdr->saddr)) {
- pr_debug("source address is unspecified, setting SAC\n");
- iphc1 |= LOWPAN_IPHC_SAC;
- /* TODO: context lookup */
- } else if (is_addr_link_local(&hdr->saddr)) {
- pr_debug("source address is link-local\n");
- iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
- LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr);
- } else {
- pr_debug("send the full source address\n");
- memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
- hc06_ptr += 16;
- }
-
- /* destination address compression */
- if (is_addr_mcast(&hdr->daddr)) {
- pr_debug("destination address is multicast: ");
- iphc1 |= LOWPAN_IPHC_M;
- if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
- pr_debug("compressed to 1 octet\n");
- iphc1 |= LOWPAN_IPHC_DAM_11;
- /* use last byte */
- *hc06_ptr = hdr->daddr.s6_addr[15];
- hc06_ptr += 1;
- } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
- pr_debug("compressed to 4 octets\n");
- iphc1 |= LOWPAN_IPHC_DAM_10;
- /* second byte + the last three */
- *hc06_ptr = hdr->daddr.s6_addr[1];
- memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
- hc06_ptr += 4;
- } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
- pr_debug("compressed to 6 octets\n");
- iphc1 |= LOWPAN_IPHC_DAM_01;
- /* second byte + the last five */
- *hc06_ptr = hdr->daddr.s6_addr[1];
- memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
- hc06_ptr += 6;
- } else {
- pr_debug("using full address\n");
- iphc1 |= LOWPAN_IPHC_DAM_00;
- memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
- hc06_ptr += 16;
- }
- } else {
- /* TODO: context lookup */
- if (is_addr_link_local(&hdr->daddr)) {
- pr_debug("dest address is unicast and link-local\n");
- iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
- LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr);
- } else {
- pr_debug("dest address is unicast: using full one\n");
- memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
- hc06_ptr += 16;
- }
- }
-
- /* UDP header compression */
- if (hdr->nexthdr == UIP_PROTO_UDP)
- lowpan_compress_udp_header(&hc06_ptr, skb);
-
- head[0] = iphc0;
- head[1] = iphc1;
-
- skb_pull(skb, sizeof(struct ipv6hdr));
- skb_reset_transport_header(skb);
- memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
- skb_reset_network_header(skb);
-
- lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
- skb->len);
+ lowpan_header_compress(skb, dev, type, daddr, saddr, len);
/*
* NOTE1: I'm still unsure about the fact that compression and WPAN
@@ -671,39 +168,38 @@ static int lowpan_header_create(struct sk_buff *skb,
* from MAC subif of the 'dev' and 'real_dev' network devices, but
* this isn't implemented in mainline yet, so currently we assign 0xff
*/
- {
- mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
- mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
- /* prepare wpan address data */
- sa.addr_type = IEEE802154_ADDR_LONG;
- sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+ sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
- memcpy(&(sa.hwaddr), saddr, 8);
- /* intra-PAN communications */
- da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+ memcpy(&(sa.hwaddr), saddr, 8);
+ /* intra-PAN communications */
+ da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
- /*
- * if the destination address is the broadcast address, use the
- * corresponding short address
- */
- if (lowpan_is_addr_broadcast(daddr)) {
- da.addr_type = IEEE802154_ADDR_SHORT;
- da.short_addr = IEEE802154_ADDR_BROADCAST;
- } else {
- da.addr_type = IEEE802154_ADDR_LONG;
- memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
-
- /* request acknowledgment */
- mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
- }
+ /*
+ * if the destination address is the broadcast address, use the
+ * corresponding short address
+ */
+ if (lowpan_is_addr_broadcast(daddr)) {
+ da.addr_type = IEEE802154_ADDR_SHORT;
+ da.short_addr = IEEE802154_ADDR_BROADCAST;
+ } else {
+ da.addr_type = IEEE802154_ADDR_LONG;
+ memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
- return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
- type, (void *)&da, (void *)&sa, skb->len);
+ /* request acknowledgment */
+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
}
+
+ return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+ type, (void *)&da, (void *)&sa, skb->len);
}
-static int lowpan_give_skb_to_devices(struct sk_buff *skb)
+static int lowpan_give_skb_to_devices(struct sk_buff *skb,
+ struct net_device *dev)
{
struct lowpan_dev_record *entry;
struct sk_buff *skb_cp;
@@ -726,31 +222,6 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb)
return stat;
}
-static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
-{
- struct sk_buff *new;
- int stat = NET_RX_SUCCESS;
-
- new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
- GFP_ATOMIC);
- kfree_skb(skb);
-
- if (!new)
- return -ENOMEM;
-
- skb_push(new, sizeof(struct ipv6hdr));
- skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
-
- new->protocol = htons(ETH_P_IPV6);
- new->pkt_type = PACKET_HOST;
-
- stat = lowpan_give_skb_to_devices(new);
-
- kfree_skb(new);
-
- return stat;
-}
-
static void lowpan_fragment_timer_expired(unsigned long entry_addr)
{
struct lowpan_fragment *entry = (struct lowpan_fragment *)entry_addr;
@@ -814,13 +285,10 @@ frame_err:
return NULL;
}
-static int
-lowpan_process_data(struct sk_buff *skb)
+static int process_data(struct sk_buff *skb)
{
- struct ipv6hdr hdr = {};
- u8 tmp, iphc0, iphc1, num_context = 0;
+ u8 iphc0, iphc1;
const struct ieee802154_addr *_saddr, *_daddr;
- int err;
lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
skb->len);
@@ -925,162 +393,11 @@ lowpan_process_data(struct sk_buff *skb)
_saddr = &mac_cb(skb)->sa;
_daddr = &mac_cb(skb)->da;
- pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1);
-
- /* another if the CID flag is set */
- if (iphc1 & LOWPAN_IPHC_CID) {
- pr_debug("CID flag is set, increase header with one\n");
- if (lowpan_fetch_skb_u8(skb, &num_context))
- goto drop;
- }
-
- hdr.version = 6;
-
- /* Traffic Class and Flow Label */
- switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
- /*
- * Traffic Class and FLow Label carried in-line
- * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
- */
- case 0: /* 00b */
- if (lowpan_fetch_skb_u8(skb, &tmp))
- goto drop;
-
- memcpy(&hdr.flow_lbl, &skb->data[0], 3);
- skb_pull(skb, 3);
- hdr.priority = ((tmp >> 2) & 0x0f);
- hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
- (hdr.flow_lbl[0] & 0x0f);
- break;
- /*
- * Traffic class carried in-line
- * ECN + DSCP (1 byte), Flow Label is elided
- */
- case 2: /* 10b */
- if (lowpan_fetch_skb_u8(skb, &tmp))
- goto drop;
-
- hdr.priority = ((tmp >> 2) & 0x0f);
- hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
- break;
- /*
- * Flow Label carried in-line
- * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
- */
- case 1: /* 01b */
- if (lowpan_fetch_skb_u8(skb, &tmp))
- goto drop;
-
- hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
- memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
- skb_pull(skb, 2);
- break;
- /* Traffic Class and Flow Label are elided */
- case 3: /* 11b */
- break;
- default:
- break;
- }
-
- /* Next Header */
- if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
- /* Next header is carried inline */
- if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr)))
- goto drop;
-
- pr_debug("NH flag is set, next header carried inline: %02x\n",
- hdr.nexthdr);
- }
-
- /* Hop Limit */
- if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
- hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
- else {
- if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
- goto drop;
- }
-
- /* Extract SAM to the tmp variable */
- tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
-
- if (iphc1 & LOWPAN_IPHC_SAC) {
- /* Source address context based uncompression */
- pr_debug("SAC bit is set. Handle context based source address.\n");
- err = lowpan_uncompress_context_based_src_addr(
- skb, &hdr.saddr, tmp);
- } else {
- /* Source address uncompression */
- pr_debug("source address stateless compression\n");
- err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
- }
-
- /* Check on error of previous branch */
- if (err)
- goto drop;
-
- /* Extract DAM to the tmp variable */
- tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
-
- /* check for Multicast Compression */
- if (iphc1 & LOWPAN_IPHC_M) {
- if (iphc1 & LOWPAN_IPHC_DAC) {
- pr_debug("dest: context-based mcast compression\n");
- /* TODO: implement this */
- } else {
- err = lowpan_uncompress_multicast_daddr(
- skb, &hdr.daddr, tmp);
- if (err)
- goto drop;
- }
- } else {
- pr_debug("dest: stateless compression\n");
- err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr);
- if (err)
- goto drop;
- }
-
- /* UDP data uncompression */
- if (iphc0 & LOWPAN_IPHC_NH_C) {
- struct udphdr uh;
- struct sk_buff *new;
- if (lowpan_uncompress_udp_header(skb, &uh))
- goto drop;
-
- /*
- * replace the compressed UDP head by the uncompressed UDP
- * header
- */
- new = skb_copy_expand(skb, sizeof(struct udphdr),
- skb_tailroom(skb), GFP_ATOMIC);
- kfree_skb(skb);
-
- if (!new)
- return -ENOMEM;
-
- skb = new;
-
- skb_push(skb, sizeof(struct udphdr));
- skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
-
- lowpan_raw_dump_table(__func__, "raw UDP header dump",
- (u8 *)&uh, sizeof(uh));
-
- hdr.nexthdr = UIP_PROTO_UDP;
- }
-
- /* Not fragmented package */
- hdr.payload_len = htons(skb->len);
-
- pr_debug("skb headroom size = %d, data length = %d\n",
- skb_headroom(skb), skb->len);
-
- pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
- "nexthdr = 0x%02x\n\thop_lim = %d\n", hdr.version,
- ntohs(hdr.payload_len), hdr.nexthdr, hdr.hop_limit);
-
- lowpan_raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
- sizeof(hdr));
- return lowpan_skb_deliver(skb, &hdr);
+ return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr,
+ _saddr->addr_type, IEEE802154_ADDR_LEN,
+ (u8 *)_daddr->hwaddr, _daddr->addr_type,
+ IEEE802154_ADDR_LEN, iphc0, iphc1,
+ lowpan_give_skb_to_devices);
unlock_and_drop:
spin_unlock_bh(&flist_lock);
@@ -1316,7 +633,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
/* Pull off the 1-byte of 6lowpan header. */
skb_pull(local_skb, 1);
- lowpan_give_skb_to_devices(local_skb);
+ lowpan_give_skb_to_devices(local_skb, NULL);
kfree_skb(local_skb);
kfree_skb(skb);
@@ -1328,7 +645,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
local_skb = skb_clone(skb, GFP_ATOMIC);
if (!local_skb)
goto drop;
- lowpan_process_data(local_skb);
+ process_data(local_skb);
kfree_skb(skb);
break;
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index 2869c05..535606d 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -232,6 +232,28 @@
dest = 16 bit inline */
#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
+static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 1)))
+ return -EINVAL;
+
+ *val = skb->data[0];
+ skb_pull(skb, 1);
+
+ return 0;
+}
+
+static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 2)))
+ return -EINVAL;
+
+ *val = (skb->data[0] << 8) | skb->data[1];
+ skb_pull(skb, 2);
+
+ return 0;
+}
+
static inline bool lowpan_fetch_skb(struct sk_buff *skb,
void *data, const unsigned int len)
{
@@ -244,4 +266,14 @@ static inline bool lowpan_fetch_skb(struct sk_buff *skb,
return false;
}
+typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+ const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+ const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+ u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
+int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, const void *_daddr,
+ const void *_saddr, unsigned int len);
+
#endif /* __6LOWPAN_H__ */
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
new file mode 100644
index 0000000..57c0b7a
--- /dev/null
+++ b/net/ieee802154/6lowpan_iphc.c
@@ -0,0 +1,807 @@
+/*
+ * Copyright 2011, Siemens AG
+ * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+/*
+ * Based on patches from Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Jon's code is based on 6lowpan implementation for Contiki which is:
+ * Copyright (c) 2008, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <linux/bitops.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include <net/af_ieee802154.h>
+
+#include "6lowpan.h"
+
+/* print data in line */
+static inline void raw_dump_inline(const char *caller, char *msg,
+ unsigned char *buf, int len)
+{
+ if (msg)
+ pr_debug("%s():%s: ", caller, msg);
+ print_hex_dump_debug("", DUMP_PREFIX_NONE,
+ 16, 1, buf, len, false);
+}
+
+/*
+ * print data in a table format:
+ *
+ * addr: xx xx xx xx xx xx
+ * addr: xx xx xx xx xx xx
+ * ...
+ */
+static inline void raw_dump_table(const char *caller, char *msg,
+ unsigned char *buf, int len)
+{
+ if (msg)
+ pr_debug("%s():%s:\n", caller, msg);
+ print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET,
+ 16, 1, buf, len, false);
+}
+
+/*
+ * Uncompress address function for source and
+ * destination address(non-multicast).
+ *
+ * address_mode is sam value or dam value.
+ */
+static int uncompress_addr(struct sk_buff *skb,
+ struct in6_addr *ipaddr, const u8 address_mode,
+ const u8 *lladdr, const u8 addr_type,
+ const u8 addr_len)
+{
+ bool fail;
+
+ switch (address_mode) {
+ case LOWPAN_IPHC_ADDR_00:
+ /* for global link addresses */
+ fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+ break;
+ case LOWPAN_IPHC_ADDR_01:
+ /* fe:80::XXXX:XXXX:XXXX:XXXX */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
+ break;
+ case LOWPAN_IPHC_ADDR_02:
+ /* fe:80::ff:fe00:XXXX */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ ipaddr->s6_addr[11] = 0xFF;
+ ipaddr->s6_addr[12] = 0xFE;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
+ break;
+ case LOWPAN_IPHC_ADDR_03:
+ fail = false;
+ switch (addr_type) {
+ case IEEE802154_ADDR_LONG:
+ /* fe:80::XXXX:XXXX:XXXX:XXXX
+ * \_________________/
+ * hwaddr
+ */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
+ /* second bit-flip (Universe/Local)
+ * is done according RFC2464
+ */
+ ipaddr->s6_addr[8] ^= 0x02;
+ break;
+ case IEEE802154_ADDR_SHORT:
+ /* fe:80::ff:fe00:XXXX
+ * \__/
+ * short_addr
+ *
+ * Universe/Local bit is zero.
+ */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ ipaddr->s6_addr[11] = 0xFF;
+ ipaddr->s6_addr[12] = 0xFE;
+ ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
+ break;
+ default:
+ pr_debug("Invalid addr_type set\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ pr_debug("Invalid address mode value: 0x%x\n", address_mode);
+ return -EINVAL;
+ }
+
+ if (fail) {
+ pr_debug("Failed to fetch skb data\n");
+ return -EIO;
+ }
+
+ raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
+ ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
+/*
+ * Uncompress address function for source context
+ * based address(non-multicast).
+ */
+static int uncompress_context_based_src_addr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 sam)
+{
+ switch (sam) {
+ case LOWPAN_IPHC_ADDR_00:
+ /* unspec address ::
+ * Do nothing, address is already ::
+ */
+ break;
+ case LOWPAN_IPHC_ADDR_01:
+ /* TODO */
+ case LOWPAN_IPHC_ADDR_02:
+ /* TODO */
+ case LOWPAN_IPHC_ADDR_03:
+ /* TODO */
+ netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
+ return -EINVAL;
+ default:
+ pr_debug("Invalid sam value: 0x%x\n", sam);
+ return -EINVAL;
+ }
+
+ raw_dump_inline(NULL,
+ "Reconstructed context based ipv6 src addr is",
+ ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
+static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
+ struct net_device *dev, skb_delivery_cb deliver_skb)
+{
+ struct sk_buff *new;
+ int stat;
+
+ new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
+ GFP_ATOMIC);
+ kfree_skb(skb);
+
+ if (!new)
+ return -ENOMEM;
+
+ skb_push(new, sizeof(struct ipv6hdr));
+ skb_reset_network_header(new);
+ skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
+
+ new->protocol = htons(ETH_P_IPV6);
+ new->pkt_type = PACKET_HOST;
+ new->dev = dev;
+
+ raw_dump_table(__func__, "raw skb data dump before receiving",
+ new->data, new->len);
+
+ stat = deliver_skb(new, dev);
+
+ kfree_skb(new);
+
+ return stat;
+}
+
+/* Uncompress function for multicast destination address,
+ * when M bit is set.
+ */
+static int
+lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 dam)
+{
+ bool fail;
+
+ switch (dam) {
+ case LOWPAN_IPHC_DAM_00:
+ /* 00: 128 bits. The full address
+ * is carried in-line.
+ */
+ fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+ break;
+ case LOWPAN_IPHC_DAM_01:
+ /* 01: 48 bits. The address takes
+ * the form ffXX::00XX:XXXX:XXXX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+ fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
+ break;
+ case LOWPAN_IPHC_DAM_10:
+ /* 10: 32 bits. The address takes
+ * the form ffXX::00XX:XXXX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+ fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
+ break;
+ case LOWPAN_IPHC_DAM_11:
+ /* 11: 8 bits. The address takes
+ * the form ff02::00XX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ ipaddr->s6_addr[1] = 0x02;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
+ break;
+ default:
+ pr_debug("DAM value has a wrong value: 0x%x\n", dam);
+ return -EINVAL;
+ }
+
+ if (fail) {
+ pr_debug("Failed to fetch skb data\n");
+ return -EIO;
+ }
+
+ raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
+ ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
+static int
+uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
+{
+ u8 tmp;
+
+ if (!uh)
+ goto err;
+
+ if (lowpan_fetch_skb_u8(skb, &tmp))
+ goto err;
+
+ if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
+ pr_debug("UDP header uncompression\n");
+ switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
+ case LOWPAN_NHC_UDP_CS_P_00:
+ memcpy(&uh->source, &skb->data[0], 2);
+ memcpy(&uh->dest, &skb->data[2], 2);
+ skb_pull(skb, 4);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_01:
+ memcpy(&uh->source, &skb->data[0], 2);
+ uh->dest =
+ skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT;
+ skb_pull(skb, 3);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_10:
+ uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT;
+ memcpy(&uh->dest, &skb->data[1], 2);
+ skb_pull(skb, 3);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_11:
+ uh->source =
+ LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4);
+ uh->dest =
+ LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f);
+ skb_pull(skb, 1);
+ break;
+ default:
+ pr_debug("ERROR: unknown UDP format\n");
+ goto err;
+ break;
+ }
+
+ pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
+ uh->source, uh->dest);
+
+ /* copy checksum */
+ memcpy(&uh->check, &skb->data[0], 2);
+ skb_pull(skb, 2);
+
+ /*
+ * UDP lenght needs to be infered from the lower layers
+ * here, we obtain the hint from the remaining size of the
+ * frame
+ */
+ uh->len = htons(skb->len + sizeof(struct udphdr));
+ pr_debug("uncompressed UDP length: src = %d", uh->len);
+ } else {
+ pr_debug("ERROR: unsupported NH format\n");
+ goto err;
+ }
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+/* TTL uncompression values */
+static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+ const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+ const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+ u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
+{
+ struct ipv6hdr hdr = {};
+ u8 tmp, num_context = 0;
+ int err;
+
+ raw_dump_table(__func__, "raw skb data dump uncompressed",
+ skb->data, skb->len);
+
+ /* another if the CID flag is set */
+ if (iphc1 & LOWPAN_IPHC_CID) {
+ pr_debug("CID flag is set, increase header with one\n");
+ if (lowpan_fetch_skb_u8(skb, &num_context))
+ goto drop;
+ }
+
+ hdr.version = 6;
+
+ /* Traffic Class and Flow Label */
+ switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
+ /*
+ * Traffic Class and FLow Label carried in-line
+ * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+ */
+ case 0: /* 00b */
+ if (lowpan_fetch_skb_u8(skb, &tmp))
+ goto drop;
+
+ memcpy(&hdr.flow_lbl, &skb->data[0], 3);
+ skb_pull(skb, 3);
+ hdr.priority = ((tmp >> 2) & 0x0f);
+ hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
+ (hdr.flow_lbl[0] & 0x0f);
+ break;
+ /*
+ * Traffic class carried in-line
+ * ECN + DSCP (1 byte), Flow Label is elided
+ */
+ case 2: /* 10b */
+ if (lowpan_fetch_skb_u8(skb, &tmp))
+ goto drop;
+
+ hdr.priority = ((tmp >> 2) & 0x0f);
+ hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
+ break;
+ /*
+ * Flow Label carried in-line
+ * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
+ */
+ case 1: /* 01b */
+ if (lowpan_fetch_skb_u8(skb, &tmp))
+ goto drop;
+
+ hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
+ memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
+ skb_pull(skb, 2);
+ break;
+ /* Traffic Class and Flow Label are elided */
+ case 3: /* 11b */
+ break;
+ default:
+ break;
+ }
+
+ /* Next Header */
+ if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+ /* Next header is carried inline */
+ if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr)))
+ goto drop;
+
+ pr_debug("NH flag is set, next header carried inline: %02x\n",
+ hdr.nexthdr);
+ }
+
+ /* Hop Limit */
+ if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
+ hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
+ else {
+ if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
+ goto drop;
+ }
+
+ /* Extract SAM to the tmp variable */
+ tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
+
+ if (iphc1 & LOWPAN_IPHC_SAC) {
+ /* Source address context based uncompression */
+ pr_debug("SAC bit is set. Handle context based source address.\n");
+ err = uncompress_context_based_src_addr(
+ skb, &hdr.saddr, tmp);
+ } else {
+ /* Source address uncompression */
+ pr_debug("source address stateless compression\n");
+ err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
+ saddr_type, saddr_len);
+ }
+
+ /* Check on error of previous branch */
+ if (err)
+ goto drop;
+
+ /* Extract DAM to the tmp variable */
+ tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
+
+ /* check for Multicast Compression */
+ if (iphc1 & LOWPAN_IPHC_M) {
+ if (iphc1 & LOWPAN_IPHC_DAC) {
+ pr_debug("dest: context-based mcast compression\n");
+ /* TODO: implement this */
+ } else {
+ err = lowpan_uncompress_multicast_daddr(
+ skb, &hdr.daddr, tmp);
+ if (err)
+ goto drop;
+ }
+ } else {
+ err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
+ daddr_type, daddr_len);
+ pr_debug("dest: stateless compression mode %d dest %pI6c\n",
+ tmp, &hdr.daddr);
+ if (err)
+ goto drop;
+ }
+
+ /* UDP data uncompression */
+ if (iphc0 & LOWPAN_IPHC_NH_C) {
+ struct udphdr uh;
+ struct sk_buff *new;
+ if (uncompress_udp_header(skb, &uh))
+ goto drop;
+
+ /*
+ * replace the compressed UDP head by the uncompressed UDP
+ * header
+ */
+ new = skb_copy_expand(skb, sizeof(struct udphdr),
+ skb_tailroom(skb), GFP_ATOMIC);
+ kfree_skb(skb);
+
+ if (!new)
+ return -ENOMEM;
+
+ skb = new;
+
+ skb_push(skb, sizeof(struct udphdr));
+ skb_reset_transport_header(skb);
+ skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+ raw_dump_table(__func__, "raw UDP header dump",
+ (u8 *)&uh, sizeof(uh));
+
+ hdr.nexthdr = UIP_PROTO_UDP;
+ }
+
+ hdr.payload_len = htons(skb->len);
+
+ pr_debug("skb headroom size = %d, data length = %d\n",
+ skb_headroom(skb), skb->len);
+
+ pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
+ "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
+ hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
+ hdr.hop_limit, &hdr.daddr);
+
+ raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
+ sizeof(hdr));
+
+ return skb_deliver(skb, &hdr, dev, deliver_skb);
+
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(lowpan_process_data);
+
+static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
+ const struct in6_addr *ipaddr,
+ const unsigned char *lladdr)
+{
+ u8 val = 0;
+
+ if (is_addr_mac_addr_based(ipaddr, lladdr)) {
+ val = 3; /* 0-bits */
+ pr_debug("address compression 0 bits\n");
+ } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
+ /* compress IID to 16 bits xxxx::XXXX */
+ memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
+ *hc06_ptr += 2;
+ val = 2; /* 16-bits */
+ raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
+ *hc06_ptr - 2, 2);
+ } else {
+ /* do not compress IID => xxxx::IID */
+ memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
+ *hc06_ptr += 8;
+ val = 1; /* 64-bits */
+ raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
+ *hc06_ptr - 8, 8);
+ }
+
+ return rol8(val, shift);
+}
+
+static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
+{
+ struct udphdr *uh = udp_hdr(skb);
+
+ if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
+ LOWPAN_NHC_UDP_4BIT_PORT) &&
+ ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
+ LOWPAN_NHC_UDP_4BIT_PORT)) {
+ pr_debug("UDP header: both ports compression to 4 bits\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
+ **(hc06_ptr + 1) = /* subtraction is faster */
+ (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
+ ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
+ *hc06_ptr += 2;
+ } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
+ LOWPAN_NHC_UDP_8BIT_PORT) {
+ pr_debug("UDP header: remove 8 bits of dest\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
+ memcpy(*hc06_ptr + 1, &uh->source, 2);
+ **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
+ *hc06_ptr += 4;
+ } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
+ LOWPAN_NHC_UDP_8BIT_PORT) {
+ pr_debug("UDP header: remove 8 bits of source\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
+ memcpy(*hc06_ptr + 1, &uh->dest, 2);
+ **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
+ *hc06_ptr += 4;
+ } else {
+ pr_debug("UDP header: can't compress\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
+ memcpy(*hc06_ptr + 1, &uh->source, 2);
+ memcpy(*hc06_ptr + 3, &uh->dest, 2);
+ *hc06_ptr += 5;
+ }
+
+ /* checksum is always inline */
+ memcpy(*hc06_ptr, &uh->check, 2);
+ *hc06_ptr += 2;
+
+ /* skip the UDP header */
+ skb_pull(skb, sizeof(struct udphdr));
+}
+
+int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, const void *_daddr,
+ const void *_saddr, unsigned int len)
+{
+ u8 tmp, iphc0, iphc1, *hc06_ptr;
+ struct ipv6hdr *hdr;
+ u8 head[100] = {};
+
+ if (type != ETH_P_IPV6)
+ return -EINVAL;
+
+ hdr = ipv6_hdr(skb);
+ hc06_ptr = head + 2;
+
+ pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
+ "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
+ hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
+ hdr->hop_limit, &hdr->daddr);
+
+ raw_dump_table(__func__, "raw skb network header dump",
+ skb_network_header(skb), sizeof(struct ipv6hdr));
+
+ /*
+ * As we copy some bit-length fields, in the IPHC encoding bytes,
+ * we sometimes use |=
+ * If the field is 0, and the current bit value in memory is 1,
+ * this does not work. We therefore reset the IPHC encoding here
+ */
+ iphc0 = LOWPAN_DISPATCH_IPHC;
+ iphc1 = 0;
+
+ /* TODO: context lookup */
+
+ raw_dump_inline(__func__, "saddr",
+ (unsigned char *)_saddr, IEEE802154_ADDR_LEN);
+ raw_dump_inline(__func__, "daddr",
+ (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
+
+ raw_dump_table(__func__,
+ "sending raw skb network uncompressed packet",
+ skb->data, skb->len);
+
+ /*
+ * Traffic class, flow label
+ * If flow label is 0, compress it. If traffic class is 0, compress it
+ * We have to process both in the same time as the offset of traffic
+ * class depends on the presence of version and flow label
+ */
+
+ /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
+ tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
+ tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
+
+ if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
+ (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
+ /* flow label can be compressed */
+ iphc0 |= LOWPAN_IPHC_FL_C;
+ if ((hdr->priority == 0) &&
+ ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+ /* compress (elide) all */
+ iphc0 |= LOWPAN_IPHC_TC_C;
+ } else {
+ /* compress only the flow label */
+ *hc06_ptr = tmp;
+ hc06_ptr += 1;
+ }
+ } else {
+ /* Flow label cannot be compressed */
+ if ((hdr->priority == 0) &&
+ ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+ /* compress only traffic class */
+ iphc0 |= LOWPAN_IPHC_TC_C;
+ *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
+ memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
+ hc06_ptr += 3;
+ } else {
+ /* compress nothing */
+ memcpy(hc06_ptr, &hdr, 4);
+ /* replace the top byte with new ECN | DSCP format */
+ *hc06_ptr = tmp;
+ hc06_ptr += 4;
+ }
+ }
+
+ /* NOTE: payload length is always compressed */
+
+ /* Next Header is compress if UDP */
+ if (hdr->nexthdr == UIP_PROTO_UDP)
+ iphc0 |= LOWPAN_IPHC_NH_C;
+
+ if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+ *hc06_ptr = hdr->nexthdr;
+ hc06_ptr += 1;
+ }
+
+ /*
+ * Hop limit
+ * if 1: compress, encoding is 01
+ * if 64: compress, encoding is 10
+ * if 255: compress, encoding is 11
+ * else do not compress
+ */
+ switch (hdr->hop_limit) {
+ case 1:
+ iphc0 |= LOWPAN_IPHC_TTL_1;
+ break;
+ case 64:
+ iphc0 |= LOWPAN_IPHC_TTL_64;
+ break;
+ case 255:
+ iphc0 |= LOWPAN_IPHC_TTL_255;
+ break;
+ default:
+ *hc06_ptr = hdr->hop_limit;
+ hc06_ptr += 1;
+ break;
+ }
+
+ /* source address compression */
+ if (is_addr_unspecified(&hdr->saddr)) {
+ pr_debug("source address is unspecified, setting SAC\n");
+ iphc1 |= LOWPAN_IPHC_SAC;
+ /* TODO: context lookup */
+ } else if (is_addr_link_local(&hdr->saddr)) {
+ iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+ LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr);
+ pr_debug("source address unicast link-local %pI6c "
+ "iphc1 0x%02x\n", &hdr->saddr, iphc1);
+ } else {
+ pr_debug("send the full source address\n");
+ memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
+ hc06_ptr += 16;
+ }
+
+ /* destination address compression */
+ if (is_addr_mcast(&hdr->daddr)) {
+ pr_debug("destination address is multicast: ");
+ iphc1 |= LOWPAN_IPHC_M;
+ if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
+ pr_debug("compressed to 1 octet\n");
+ iphc1 |= LOWPAN_IPHC_DAM_11;
+ /* use last byte */
+ *hc06_ptr = hdr->daddr.s6_addr[15];
+ hc06_ptr += 1;
+ } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
+ pr_debug("compressed to 4 octets\n");
+ iphc1 |= LOWPAN_IPHC_DAM_10;
+ /* second byte + the last three */
+ *hc06_ptr = hdr->daddr.s6_addr[1];
+ memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
+ hc06_ptr += 4;
+ } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
+ pr_debug("compressed to 6 octets\n");
+ iphc1 |= LOWPAN_IPHC_DAM_01;
+ /* second byte + the last five */
+ *hc06_ptr = hdr->daddr.s6_addr[1];
+ memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
+ hc06_ptr += 6;
+ } else {
+ pr_debug("using full address\n");
+ iphc1 |= LOWPAN_IPHC_DAM_00;
+ memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
+ hc06_ptr += 16;
+ }
+ } else {
+ /* TODO: context lookup */
+ if (is_addr_link_local(&hdr->daddr)) {
+ iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+ LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
+ pr_debug("dest address unicast link-local %pI6c "
+ "iphc1 0x%02x\n", &hdr->daddr, iphc1);
+ } else {
+ pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
+ memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
+ hc06_ptr += 16;
+ }
+ }
+
+ /* UDP header compression */
+ if (hdr->nexthdr == UIP_PROTO_UDP)
+ compress_udp_header(&hc06_ptr, skb);
+
+ head[0] = iphc0;
+ head[1] = iphc1;
+
+ skb_pull(skb, sizeof(struct ipv6hdr));
+ skb_reset_transport_header(skb);
+ memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+ skb_reset_network_header(skb);
+
+ pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len);
+
+ raw_dump_table(__func__, "raw skb data dump compressed",
+ skb->data, skb->len);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lowpan_header_compress);
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index d7716d6..951a83e 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
-obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
+obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 6lowpan_iphc.o
ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
af_802154-y := af_ieee802154.o raw.o dgram.o
--
1.8.3.1
^ permalink raw reply related
* [PATCH v10 0/5] Bluetooth LE 6LoWPAN
From: Jukka Rissanen @ 2013-12-11 15:05 UTC (permalink / raw)
To: linux-bluetooth
Hi,
this is 6LoWPAN code for BT LE as described in
http://tools.ietf.org/html/draft-ietf-6lo-btle-00
v10:
- too many network interface were created if there was
more than one 6lowpan connection via same hci device
- fixed the variable names to be more consistent
- refactored the network device and peer list handling
- more indentation fixes
v9:
- code style issues fixed in patch 4
- removed obsolete code from patch 5
v8:
- misc changes to patches 4 and 5 according to Marcel's
comments
- added Alex's Acked-by to patch 1
v7:
- rebased on top of current bluetooth
- David Miller acked the patches 2 and 3 so adding Acked-by
to those two patches
v6:
- Common IP header compression code for IEEE 802154 and Bluetooth
moved to net/ieee802154/6lowpan_iphc.c. This is in patch 1 which
is also sent separately to netdev ml.
- New ARPHRD type in patches 2 and 3 are also sent to netdev ml.
- fixes when counting number of 6lowpan peers (was not atomic)
v5:
- Moved the header compression functionality to net/core/6lowpan.c
and rebased both BT and IEEE 802154 code to use it in patch 1.
I will send a separate patch to net-next for comments.
- locking fixes
- debugfs handling moved to hci_core.c
- misc changes according to Marcel's comments
v4:
- removed the route setting code, neighbour discovery
should allow the devices to discover each other
- fix the uncompression of Traffic Class in IPv6 header,
this makes ssh to work between devices over a BT 6lowpan link
- removed setting of /proc conf options, they were useless
and not to be done in kernel module anyway
v3:
- misc changes according to Marcel's comments
- supports multiple connections / interface
- removed unused fragmentation code
- setup 6lowpan connection automatically if enabled via debugfs
The automatic 6lowpan enabling is done by setting
echo 1 > /sys/kernel/debug/bluetooth/hci0/6lowpan
before devices are connected.
v2:
- Change ARPHRD_IEEE802154 to ARPHRD_RAWIP. The generic code
in patches 1 and 2 is also sent to netdev mailing list.
- Sending route exporting patch 5 to netdev ml
- Check private/public BT address and toggle universal/local bit
accordingly in patch 3.
- The virtual interface template name is now shorter (bt%d)
- Various function name renames
- devtype of the interface set to "bluetooth"
v1:
- initial release
TODO:
- Discovery of 6LoWPAN service needs be automatic (UUID support)
- Enable/disable header compression for easier debugging
Known issues:
- no UUID handling yet
Cheers,
Jukka
Jukka Rissanen (5):
6lowpan: Moving generic compression code into 6lowpan_iphc.c
net: if_arp: add ARPHRD_6LOWPAN type
ipv6: Add checks for 6LOWPAN ARP type
Bluetooth: Enable 6LoWPAN support for BT LE devices
Bluetooth: Manually enable or disable 6LoWPAN between devices
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 1 +
include/net/bluetooth/l2cap.h | 1 +
include/uapi/linux/if_arp.h | 1 +
net/bluetooth/6lowpan.c | 886 +++++++++++++++++++++++++++++++++++++++
net/bluetooth/6lowpan.h | 26 ++
net/bluetooth/Makefile | 6 +-
net/bluetooth/hci_core.c | 45 ++
net/bluetooth/hci_event.c | 3 +
net/bluetooth/l2cap_core.c | 12 +
net/ieee802154/6lowpan.c | 753 ++-------------------------------
net/ieee802154/6lowpan.h | 32 ++
net/ieee802154/6lowpan_iphc.c | 807 +++++++++++++++++++++++++++++++++++
net/ieee802154/Makefile | 2 +-
net/ipv6/addrconf.c | 4 +-
15 files changed, 1859 insertions(+), 721 deletions(-)
create mode 100644 net/bluetooth/6lowpan.c
create mode 100644 net/bluetooth/6lowpan.h
create mode 100644 net/ieee802154/6lowpan_iphc.c
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH 1/2] android/tester: Fix closing file descriptor
From: Johan Hedberg @ 2013-12-11 13:51 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1386762359-16645-1-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Wed, Dec 11, 2013, Marcin Kraglak wrote:
> Don't close file descriptor if failed to create it.
> ---
> android/android-tester.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
Both patches have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 1/9] android/bluetooth: Add support for reporting adapter type property
From: Johan Hedberg @ 2013-12-11 13:50 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1386757887-29018-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Wed, Dec 11, 2013, Szymon Janc wrote:
> This allows to get property with adapter type.
> ---
> android/bluetooth.c | 32 +++++++++++++++++++++++++++++---
> android/hal-msg.h | 4 ++++
> 2 files changed, 33 insertions(+), 3 deletions(-)
All patches in this set have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH BlueZ] build: Add coverage support
From: Marcel Holtmann @ 2013-12-11 13:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <CABBYNZJnpr4ddFRvZakjQ6dhK+acxfteow52bO4GZo++M=M5dw@mail.gmail.com>
Hi Luiz,
>>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>>
>>> ---
>>> Makefile.am | 18 ++++++++++++++++++
>>> acinclude.m4 | 9 +++++++++
>>> bootstrap-configure | 1 +
>>> configure.ac | 2 ++
>>> 4 files changed, 30 insertions(+)
>>>
>>> diff --git a/Makefile.am b/Makefile.am
>>> index 15cc149..1a59532 100644
>>> --- a/Makefile.am
>>> +++ b/Makefile.am
>>> @@ -331,5 +331,23 @@ lib/bluetooth/%.h: lib/%.h
>>> $(AM_V_at)$(MKDIR_P) lib/bluetooth
>>> $(AM_V_GEN)$(LN_S) -f "$(abs_top_builddir)"/$< $@
>>>
>>> +if COVERAGE
>>
>> maybe we should just make this depend on maintainer-mode.
>
> We could, but I suggest you do a quick run with this version to see if
> it is acceptable for maintainer-mode since it does increase quite a
> bit the build time for me so perhaps we should keep it separately.
let see how bad it actually is.
>>> +clean-coverage:
>>> + $(RM) -r coverage
>>> + @find . -name "*.gcda" -exec $(RM) {} \;
>>> + $(LCOV) --directory . --zerocounters
>>> +
>>> +check-coverage:
>>> + @make check
>>> + $(AM_V_at)$(MKDIR_P) -p coverage
>>> + $(LCOV) --compat-libtool --directory . --capture --output-file \
>>> + coverage/check.info
>>> + @genhtml -o coverage/ coverage/check.info
>>> +
>>> clean-local:
>>> + @make clean-coverage
>>> $(RM) -r lib/bluetooth
>>> +else
>>> +clean-local:
>>> + $(RM) -r lib/bluetooth
>>> +endif
>>> diff --git a/acinclude.m4 b/acinclude.m4
>>> index 2065852..e5eb481 100644
>>> --- a/acinclude.m4
>>> +++ b/acinclude.m4
>>> @@ -51,6 +51,15 @@ AC_DEFUN([MISC_FLAGS], [
>>> misc_ldflags="$misc_ldflags -pie"
>>> fi
>>> ])
>>> + AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],
>>> + [enable coverage flags]), [
>>> + AC_PATH_PROG([LCOV], [lcov])
>>> + if (test "$LCOV" && test "${enableval}" = "yes"); then
>>> + misc_cflags="$misc_cflags -ftest-coverage"
>>> + misc_cflags="$misc_cflags -fprofile-arcs"
>>> + misc_ldflags="$misc_ldflags -gcov"
>>> + fi
>>> + ])
>>> AC_SUBST([MISC_CFLAGS], $misc_cflags)
>>> AC_SUBST([MISC_LDFLAGS], $misc_ldflags)
>>> ])
>>> diff --git a/bootstrap-configure b/bootstrap-configure
>>> index c7f08ed..35aa98b 100755
>>> --- a/bootstrap-configure
>>> +++ b/bootstrap-configure
>>> @@ -14,4 +14,5 @@ fi
>>> --enable-experimental \
>>> --enable-android \
>>> --enable-sixaxis \
>>> + --enable-coverage \
>>> --disable-datafiles $*
>>> diff --git a/configure.ac b/configure.ac
>>> index 18d0b55..c55924f 100644
>>> --- a/configure.ac
>>> +++ b/configure.ac
>>> @@ -252,4 +252,6 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
>>> [enable_android=${enableval}])
>>> AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
>>>
>>> +AM_CONDITIONAL([COVERAGE], [test "$LCOV”])
>>
>> I do not like this one. The test should check enable_xxx variables. I rather have configure abort with error if some programs or dependencies are not found.
>
> Okay, Ive named it LCOV because it actually checks for lcov binary and
> then uses it in Makefile.am at check-coverage and clean-coverage, it
> comes from AC_PATH_PROG([LCOV], [lcov]). I can do AC_MSG_ERROR if lcov
> is not found, is that how you want it? I couldn't make AM_CONDITIONAL
> within MISC_FLAGS that why Ive moved it to configure.ac.
Yes. Just error out and abort configure.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 00/10] Refactoring bnep code to reduce redundancy
From: Johan Hedberg @ 2013-12-11 13:33 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1386756825-934-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Wed, Dec 11, 2013, Ravi kumar Veeramally wrote:
> bnep: Rename bnep_kill_connection to bnep_conndel
> bnep: Rename send ctrl_rsp and make it global
> bnep: Move bnep related calls to bnep.h|c
> profiles/network/server: Delete function which does nothing
> android/pan: Fix missing cleanup calls
> android/pan: Fix minor white space
The above patches have been applied. As we discussed offline, the others
were either dropped or need some extra work
Johan
^ permalink raw reply
* Re: [PATCH BlueZ] build: Add coverage support
From: Luiz Augusto von Dentz @ 2013-12-11 12:55 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <4818FD30-C986-47E0-8441-E58938077D45@holtmann.org>
Hi Marcel,
On Wed, Dec 11, 2013 at 2:00 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Luiz,
>
>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>
>> ---
>> Makefile.am | 18 ++++++++++++++++++
>> acinclude.m4 | 9 +++++++++
>> bootstrap-configure | 1 +
>> configure.ac | 2 ++
>> 4 files changed, 30 insertions(+)
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 15cc149..1a59532 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -331,5 +331,23 @@ lib/bluetooth/%.h: lib/%.h
>> $(AM_V_at)$(MKDIR_P) lib/bluetooth
>> $(AM_V_GEN)$(LN_S) -f "$(abs_top_builddir)"/$< $@
>>
>> +if COVERAGE
>
> maybe we should just make this depend on maintainer-mode.
We could, but I suggest you do a quick run with this version to see if
it is acceptable for maintainer-mode since it does increase quite a
bit the build time for me so perhaps we should keep it separately.
>> +clean-coverage:
>> + $(RM) -r coverage
>> + @find . -name "*.gcda" -exec $(RM) {} \;
>> + $(LCOV) --directory . --zerocounters
>> +
>> +check-coverage:
>> + @make check
>> + $(AM_V_at)$(MKDIR_P) -p coverage
>> + $(LCOV) --compat-libtool --directory . --capture --output-file \
>> + coverage/check.inf=
o
>> + @genhtml -o coverage/ coverage/check.info
>> +
>> clean-local:
>> + @make clean-coverage
>> $(RM) -r lib/bluetooth
>> +else
>> +clean-local:
>> + $(RM) -r lib/bluetooth
>> +endif
>> diff --git a/acinclude.m4 b/acinclude.m4
>> index 2065852..e5eb481 100644
>> --- a/acinclude.m4
>> +++ b/acinclude.m4
>> @@ -51,6 +51,15 @@ AC_DEFUN([MISC_FLAGS], [
>> misc_ldflags=3D"$misc_ldflags -pie"
>> fi
>> ])
>> + AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],
>> + [enable coverage flags]), [
>> + AC_PATH_PROG([LCOV], [lcov])
>> + if (test "$LCOV" && test "${enableval}" =3D "yes"); then
>> + misc_cflags=3D"$misc_cflags -ftest-coverage"
>> + misc_cflags=3D"$misc_cflags -fprofile-arcs"
>> + misc_ldflags=3D"$misc_ldflags -gcov"
>> + fi
>> + ])
>> AC_SUBST([MISC_CFLAGS], $misc_cflags)
>> AC_SUBST([MISC_LDFLAGS], $misc_ldflags)
>> ])
>> diff --git a/bootstrap-configure b/bootstrap-configure
>> index c7f08ed..35aa98b 100755
>> --- a/bootstrap-configure
>> +++ b/bootstrap-configure
>> @@ -14,4 +14,5 @@ fi
>> --enable-experimental \
>> --enable-android \
>> --enable-sixaxis \
>> + --enable-coverage \
>> --disable-datafiles $*
>> diff --git a/configure.ac b/configure.ac
>> index 18d0b55..c55924f 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -252,4 +252,6 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-andr=
oid],
>> [enable_android=3D${enableval}])
>> AM_CONDITIONAL(ANDROID, test "${enable_android}" =3D "yes")
>>
>> +AM_CONDITIONAL([COVERAGE], [test "$LCOV=94])
>
> I do not like this one. The test should check enable_xxx variables. I rat=
her have configure abort with error if some programs or dependencies are no=
t found.
Okay, Ive named it LCOV because it actually checks for lcov binary and
then uses it in Makefile.am at check-coverage and clean-coverage, it
comes from AC_PATH_PROG([LCOV], [lcov]). I can do AC_MSG_ERROR if lcov
is not found, is that how you want it? I couldn't make AM_CONDITIONAL
within MISC_FLAGS that why Ive moved it to configure.ac.
--=20
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH 3/3] android/pts: Add PTS test results for DID
From: Szymon Janc @ 2013-12-11 12:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386766179-8812-1-git-send-email-szymon.janc@tieto.com>
This will allow for better tracking of current state of implementation.
---
android/pts-did.txt | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 android/pts-did.txt
diff --git a/android/pts-did.txt b/android/pts-did.txt
new file mode 100644
index 0000000..c44f56c
--- /dev/null
+++ b/android/pts-did.txt
@@ -0,0 +1,19 @@
+PTS test results for DID
+
+PTS version: 5.0
+Tested: 11.12.2013
+
+Results:
+PASS test passed
+FAIL test failed
+INC test is inconclusive
+N/A test is disabled due to PICS setup
+
+-------------------------------------------------------------------------------
+Test Name Result Notes
+-------------------------------------------------------------------------------
+TC_SDI_BV_1_I PASS IUT must be discoverable
+TC_SDI_BV_2_I PASS IUT must be discoverable
+TC_SDI_BV_3_I PASS IUT must be discoverable
+TC_SDI_BV_4_I PASS IUT must be discoverable
+-------------------------------------------------------------------------------
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/3] android/pts: Add PTS PIXIT for DID
From: Szymon Janc @ 2013-12-11 12:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386766179-8812-1-git-send-email-szymon.janc@tieto.com>
This complements PTS PICS configuration.
---
android/pixit-did.txt | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 android/pixit-did.txt
diff --git a/android/pixit-did.txt b/android/pixit-did.txt
new file mode 100644
index 0000000..2527845
--- /dev/null
+++ b/android/pixit-did.txt
@@ -0,0 +1,22 @@
+DID PIXIT for the PTS tool.
+
+* - different than PTS defaults
+& - should be set to IUT Bluetooth address
+
+ Required PIXIT settings
+-------------------------------------------------------------------------------
+Parameter Name Value
+-------------------------------------------------------------------------------
+TSPX_security_enabled False
+TSPX_ClientExecutableURL False (*)
+TSPX_ServiceDescription False (*)
+TSPX_DocumentationURL False (*)
+TSPX_bd_addr_iut 112233445566 (*&)
+TSPX_class_of_device_pts 200404
+TSPX_device_search_time 30
+TSPX_delete_link_key False
+TSPX_pin_code 0000
+TSPX_time_guard 200000
+TSPX_use_implicit_send True
+TSPX_secure_simple_pairing_pass_key_confirmation False
+-------------------------------------------------------------------------------
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/3] android/pts: Remove PIXIT info from DID PICS file
From: Szymon Janc @ 2013-12-11 12:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
PIXIT values will be stored in separate file.
---
android/pics-did.txt | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/android/pics-did.txt b/android/pics-did.txt
index e8c914a..8f92bc1 100644
--- a/android/pics-did.txt
+++ b/android/pics-did.txt
@@ -29,14 +29,3 @@ TSPC_DID_1_5 True Primary Record (M)
TSPC_DID_1_6 True Vendor ID Source (M)
TSPC_ALL False Turns on all the test cases
-------------------------------------------------------------------------------
-
-
- Required PIXIT settings
--------------------------------------------------------------------------------
-Parameter Name Value
--------------------------------------------------------------------------------
-TSPX_ClientExecutableURL False
-TSPX_ServiceDescription False
-TSPX_DocumentationURL False
--------------------------------------------------------------------------------
-Other should be set according to Tester's test environment.
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH] android/tester: Fix closing invalid fd
From: Andrei Emeltchenko @ 2013-12-11 12:02 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386762298-31678-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
On Wed, Dec 11, 2013 at 01:44:58PM +0200, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> This fixes possible closing invalid fd in a case socket() fails
> ---
> android/android-tester.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/android/android-tester.c b/android/android-tester.c
> index 09c76c9..12d7613 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -357,8 +357,10 @@ static void emulator(int pipe, int hci_index)
> ssize_t len;
>
> fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
> - if (fd < 0)
> - goto failed;
> + if (fd < 0) {
> + close(pipe)
sorry did not check this missing ;, just apply patches from marcin
Best regards
Andrei Emeltchenko
> + return;
> + }
>
> tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
> tv.tv_usec = 0;
> @@ -374,7 +376,6 @@ static void emulator(int pipe, int hci_index)
> }
>
> len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
> -
> if (len != sizeof(EMULATOR_SIGNAL))
> goto failed;
>
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH BlueZ] build: Add coverage support
From: Marcel Holtmann @ 2013-12-11 12:00 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1386759341-14346-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> ---
> Makefile.am | 18 ++++++++++++++++++
> acinclude.m4 | 9 +++++++++
> bootstrap-configure | 1 +
> configure.ac | 2 ++
> 4 files changed, 30 insertions(+)
>
> diff --git a/Makefile.am b/Makefile.am
> index 15cc149..1a59532 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -331,5 +331,23 @@ lib/bluetooth/%.h: lib/%.h
> $(AM_V_at)$(MKDIR_P) lib/bluetooth
> $(AM_V_GEN)$(LN_S) -f "$(abs_top_builddir)"/$< $@
>
> +if COVERAGE
maybe we should just make this depend on maintainer-mode.
> +clean-coverage:
> + $(RM) -r coverage
> + @find . -name "*.gcda" -exec $(RM) {} \;
> + $(LCOV) --directory . --zerocounters
> +
> +check-coverage:
> + @make check
> + $(AM_V_at)$(MKDIR_P) -p coverage
> + $(LCOV) --compat-libtool --directory . --capture --output-file \
> + coverage/check.info
> + @genhtml -o coverage/ coverage/check.info
> +
> clean-local:
> + @make clean-coverage
> $(RM) -r lib/bluetooth
> +else
> +clean-local:
> + $(RM) -r lib/bluetooth
> +endif
> diff --git a/acinclude.m4 b/acinclude.m4
> index 2065852..e5eb481 100644
> --- a/acinclude.m4
> +++ b/acinclude.m4
> @@ -51,6 +51,15 @@ AC_DEFUN([MISC_FLAGS], [
> misc_ldflags="$misc_ldflags -pie"
> fi
> ])
> + AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],
> + [enable coverage flags]), [
> + AC_PATH_PROG([LCOV], [lcov])
> + if (test "$LCOV" && test "${enableval}" = "yes"); then
> + misc_cflags="$misc_cflags -ftest-coverage"
> + misc_cflags="$misc_cflags -fprofile-arcs"
> + misc_ldflags="$misc_ldflags -gcov"
> + fi
> + ])
> AC_SUBST([MISC_CFLAGS], $misc_cflags)
> AC_SUBST([MISC_LDFLAGS], $misc_ldflags)
> ])
> diff --git a/bootstrap-configure b/bootstrap-configure
> index c7f08ed..35aa98b 100755
> --- a/bootstrap-configure
> +++ b/bootstrap-configure
> @@ -14,4 +14,5 @@ fi
> --enable-experimental \
> --enable-android \
> --enable-sixaxis \
> + --enable-coverage \
> --disable-datafiles $*
> diff --git a/configure.ac b/configure.ac
> index 18d0b55..c55924f 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -252,4 +252,6 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
> [enable_android=${enableval}])
> AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
>
> +AM_CONDITIONAL([COVERAGE], [test "$LCOV”])
I do not like this one. The test should check enable_xxx variables. I rather have configure abort with error if some programs or dependencies are not found.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH RFC] tty_ldisc: add more limits to the @write_wakeup
From: Peter Hurley @ 2013-12-11 11:47 UTC (permalink / raw)
To: Huang Shijie; +Cc: gregkh, linux-serial, marcel, linux-bluetooth
In-Reply-To: <52A809BC.2040909@freescale.com>
On 12/11/2013 01:44 AM, Huang Shijie wrote:
> 于 2013年12月07日 00:18, Peter Hurley 写道:
>> hci_uart_tx_wakeup() should perform the actual tx in a work item.
> Does the "work item" mean a workqueue or a tasklet?
> This patch is used to tell the line discipline writers to send the data in the workqueue or a tasklet.
Yes, "work item" means struct work_struct.
Regards,
Peter Hurley
^ permalink raw reply
* [PATCH 2/2] android/tester: Remove not needed line
From: Marcin Kraglak @ 2013-12-11 11:45 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386762359-16645-1-git-send-email-marcin.kraglak@tieto.com>
diff --git a/android/android-tester.c b/android/android-tester.c
index d7e80fb..a36c10a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -374,7 +374,6 @@ static void emulator(int pipe, int hci_index)
}
len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
-
if (len != sizeof(EMULATOR_SIGNAL))
goto failed;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 1/2] android/tester: Fix closing file descriptor
From: Marcin Kraglak @ 2013-12-11 11:45 UTC (permalink / raw)
To: linux-bluetooth
Don't close file descriptor if failed to create it.
---
android/android-tester.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 09c76c9..d7e80fb 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -390,7 +390,9 @@ static void emulator(int pipe, int hci_index)
failed:
close(pipe);
- close(fd);
+
+ if (fd >= 0)
+ close(fd);
}
static void adapter_state_changed_cb(bt_state_t state)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] android/tester: Fix closing invalid fd
From: Andrei Emeltchenko @ 2013-12-11 11:44 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This fixes possible closing invalid fd in a case socket() fails
---
android/android-tester.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 09c76c9..12d7613 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -357,8 +357,10 @@ static void emulator(int pipe, int hci_index)
ssize_t len;
fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (fd < 0)
- goto failed;
+ if (fd < 0) {
+ close(pipe)
+ return;
+ }
tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
tv.tv_usec = 0;
@@ -374,7 +376,6 @@ static void emulator(int pipe, int hci_index)
}
len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
-
if (len != sizeof(EMULATOR_SIGNAL))
goto failed;
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH v4 1/7] android/tester: Add android-tester
From: Luiz Augusto von Dentz @ 2013-12-11 11:15 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1386758797-1809-1-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Wed, Dec 11, 2013 at 12:46 PM, Marcin Kraglak
<marcin.kraglak@tieto.com> wrote:
> This commit add android-tester.c to tree and Makefile.am.
> This will contain set of unit tests for testing android daemon.
> ---
> .gitignore | 1 +
> android/Makefile.am | 4 ++++
> android/android-tester.c | 21 +++++++++++++++++++++
> 3 files changed, 26 insertions(+)
> create mode 100644 android/android-tester.c
>
> diff --git a/.gitignore b/.gitignore
> index 2d3435a..c570728 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -107,3 +107,4 @@ unit/test-*.trs
> android/system-emulator
> android/bluetoothd
> android/haltest
> +android/android-tester
> diff --git a/android/Makefile.am b/android/Makefile.am
> index df04762..0768985 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -83,6 +83,10 @@ android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android \
>
> android_haltest_LDFLAGS = -pthread
>
> +noinst_PROGRAMS += android/android-tester
> +
> +android_android_tester_SOURCES = android/android-tester.c
> +
> endif
>
> EXTRA_DIST += android/Android.mk android/hal-ipc-api.txt android/README \
> diff --git a/android/android-tester.c b/android/android-tester.c
> new file mode 100644
> index 0000000..f5c42b0
> --- /dev/null
> +++ b/android/android-tester.c
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (C) 2013 Intel Corporation
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + *
> + */
> +
> +int main(int argc, char *argv[])
> +{
> + return 0;
> +}
> --
> 1.8.3.1
Applied, thanks.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH v4 3/7] android/tester: Start emulator in new process
From: Andrei Emeltchenko @ 2013-12-11 11:10 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1386758797-1809-3-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Wed, Dec 11, 2013 at 11:46:33AM +0100, Marcin Kraglak wrote:
> This is needed because bluetooth->init call is blocking,
> and we have to emulate normal behaviour of android environment.
> That process will exit if it won't receive any message in 2 sec
> or when bluetoothd will exit. Main tester thread will wait for
> this process in teardown method.
> ---
> android/android-tester.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 131 insertions(+), 1 deletion(-)
>
> diff --git a/android/android-tester.c b/android/android-tester.c
> index 498da22..ad7aa39 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -15,9 +15,15 @@
> *
> */
>
> +#include <stdlib.h>
> #include <unistd.h>
>
> #include <glib.h>
> +#include <sys/socket.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include <sys/un.h>
> +#include <libgen.h>
>
> #include "lib/bluetooth.h"
> #include "lib/mgmt.h"
> @@ -29,14 +35,20 @@
> struct generic_data {
> };
>
> +#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
> +#define EMULATOR_SIGNAL "emulator_started"
> +
> struct test_data {
> struct mgmt *mgmt;
> uint16_t mgmt_index;
> struct hciemu *hciemu;
> enum hciemu_type hciemu_type;
> const struct generic_data *test_data;
> + pid_t bluetoothd_pid;
> };
>
> +static char exec_dir[PATH_MAX + 1];
> +
> static void read_info_callback(uint8_t status, uint16_t length,
> const void *param, void *user_data)
> {
> @@ -165,13 +177,129 @@ static void test_post_teardown(const void *test_data)
> data->hciemu = NULL;
> }
>
> +static void bluetoothd_start(int hci_index)
> +{
> + char prg_name[PATH_MAX + 1];
> + char index[8];
> + char *prg_argv[4];
> +
> + snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir, "bluetoothd");
> + snprintf(index, sizeof(index), "%d", hci_index);
> +
> + prg_argv[0] = prg_name;
> + prg_argv[1] = "-i";
> + prg_argv[2] = index;
> + prg_argv[3] = NULL;
> +
> + if (!tester_use_debug())
> + fclose(stderr);
> +
> + execve(prg_argv[0], prg_argv, NULL);
> +}
> +
> +static void emulator(int pipe, int hci_index)
> +{
> + static const char SYSTEM_SOCKET_PATH[] = "\0android_system";
> + char buf[1024];
> + struct sockaddr_un addr;
> + struct timeval tv;
> + int fd;
> + ssize_t len;
> +
> + fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
> + if (fd < 0)
> + goto failed;
return? otherwise you close invalid fd, or check fd in failed
> +
> + tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
> + tv.tv_usec = 0;
> + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
> +
> + memset(&addr, 0, sizeof(addr));
> + addr.sun_family = AF_UNIX;
> + memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH));
> +
> + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> + perror("Failed to bind system socket");
> + goto failed;
> + }
> +
> + len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
> +
we do not need here empty space
Best regards
Andrei Emeltchenko
> + if (len != sizeof(EMULATOR_SIGNAL))
> + goto failed;
> +
> + memset(buf, 0, sizeof(buf));
> +
> + len = read(fd, buf, sizeof(buf));
> + if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd")))
> + goto failed;
> +
> + close(pipe);
> + close(fd);
> + bluetoothd_start(hci_index);
> +
> +failed:
> + close(pipe);
> + close(fd);
> +}
> +
> +static void setup(struct test_data *data)
> +{
> + int signal_fd[2];
> + char buf[1024];
> + pid_t pid;
> + int len;
> +
> + if (pipe(signal_fd)) {
> + tester_setup_failed();
> + return;
> + }
> +
> + pid = fork();
> +
> + if (pid < 0) {
> + close(signal_fd[0]);
> + close(signal_fd[1]);
> + tester_setup_failed();
> + return;
> + }
> +
> + if (pid == 0) {
> + if (!tester_use_debug())
> + fclose(stderr);
> +
> + close(signal_fd[0]);
> + emulator(signal_fd[1], data->mgmt_index);
> + exit(0);
> + }
> +
> + close(signal_fd[1]);
> + data->bluetoothd_pid = pid;
> +
> + len = read(signal_fd[0], buf, sizeof(buf));
> + if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
> + close(signal_fd[0]);
> + tester_setup_failed();
> + return;
> + }
> +}
> +
> static void setup_base(const void *test_data)
> {
> - tester_setup_failed();
> + struct test_data *data = tester_get_data();
> +
> + setup(data);
> +
> + tester_setup_complete();
> }
>
> static void teardown(const void *test_data)
> {
> + struct test_data *data = tester_get_data();
> +
> + if (data->bluetoothd_pid)
> + waitpid(data->bluetoothd_pid, NULL, 0);
> +
> tester_teardown_complete();
> }
>
> @@ -194,6 +322,8 @@ static void controller_setup(const void *test_data)
>
> int main(int argc, char *argv[])
> {
> + snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
> +
> tester_init(&argc, &argv);
>
> test_bredrle("Test Init", NULL, setup_base, controller_setup, teardown);
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH BlueZ] build: Add coverage support
From: Luiz Augusto von Dentz @ 2013-12-11 10:55 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
Makefile.am | 18 ++++++++++++++++++
acinclude.m4 | 9 +++++++++
bootstrap-configure | 1 +
configure.ac | 2 ++
4 files changed, 30 insertions(+)
diff --git a/Makefile.am b/Makefile.am
index 15cc149..1a59532 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -331,5 +331,23 @@ lib/bluetooth/%.h: lib/%.h
$(AM_V_at)$(MKDIR_P) lib/bluetooth
$(AM_V_GEN)$(LN_S) -f "$(abs_top_builddir)"/$< $@
+if COVERAGE
+clean-coverage:
+ $(RM) -r coverage
+ @find . -name "*.gcda" -exec $(RM) {} \;
+ $(LCOV) --directory . --zerocounters
+
+check-coverage:
+ @make check
+ $(AM_V_at)$(MKDIR_P) -p coverage
+ $(LCOV) --compat-libtool --directory . --capture --output-file \
+ coverage/check.info
+ @genhtml -o coverage/ coverage/check.info
+
clean-local:
+ @make clean-coverage
$(RM) -r lib/bluetooth
+else
+clean-local:
+ $(RM) -r lib/bluetooth
+endif
diff --git a/acinclude.m4 b/acinclude.m4
index 2065852..e5eb481 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -51,6 +51,15 @@ AC_DEFUN([MISC_FLAGS], [
misc_ldflags="$misc_ldflags -pie"
fi
])
+ AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],
+ [enable coverage flags]), [
+ AC_PATH_PROG([LCOV], [lcov])
+ if (test "$LCOV" && test "${enableval}" = "yes"); then
+ misc_cflags="$misc_cflags -ftest-coverage"
+ misc_cflags="$misc_cflags -fprofile-arcs"
+ misc_ldflags="$misc_ldflags -gcov"
+ fi
+ ])
AC_SUBST([MISC_CFLAGS], $misc_cflags)
AC_SUBST([MISC_LDFLAGS], $misc_ldflags)
])
diff --git a/bootstrap-configure b/bootstrap-configure
index c7f08ed..35aa98b 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -14,4 +14,5 @@ fi
--enable-experimental \
--enable-android \
--enable-sixaxis \
+ --enable-coverage \
--disable-datafiles $*
diff --git a/configure.ac b/configure.ac
index 18d0b55..c55924f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,4 +252,6 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
[enable_android=${enableval}])
AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
+AM_CONDITIONAL([COVERAGE], [test "$LCOV"])
+
AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 7/7] android/tester: Add status check and adapter enable, disable test cases
From: Marcin Kraglak @ 2013-12-11 10:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Grzegorz Kolodziejczyk
In-Reply-To: <1386758797-1809-1-git-send-email-marcin.kraglak@tieto.com>
From: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>
This adds handling of status check, enabled adapter setup method,
disable and enable fail test case.
---
android/android-tester.c | 108 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 103 insertions(+), 5 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 0dc1edf..09c76c9 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -46,6 +46,7 @@
enum hal_bluetooth_callbacks_id {
adapter_test_end,
+ adapter_test_setup_mode,
adapter_state_changed_on,
adapter_state_changed_off,
adapter_prop_bdaddr,
@@ -59,6 +60,7 @@ enum hal_bluetooth_callbacks_id {
};
struct generic_data {
+ uint8_t expected_adapter_status;
uint32_t expect_settings_set;
uint8_t expected_hal_callbacks[];
};
@@ -78,6 +80,7 @@ struct test_data {
bool mgmt_settings_set;
bool hal_cb_called;
+ bool status_checked;
GSList *expected_callbacks;
};
@@ -88,8 +91,13 @@ static void test_update_state(void)
{
struct test_data *data = tester_get_data();
- if (data->mgmt_settings_set && data->hal_cb_called)
- tester_test_passed();
+ if (!(data->mgmt_settings_set))
+ return;
+ if (!(data->hal_cb_called))
+ return;
+ if (!(data->status_checked))
+ return;
+ tester_test_passed();
}
static void test_mgmt_settings_set(struct test_data *data)
@@ -143,10 +151,38 @@ static void mgmt_cb_init(struct test_data *data)
command_generic_new_settings, NULL, NULL);
}
+static void expected_status_init(struct test_data *data)
+{
+ if (!(data->test_data->expected_adapter_status))
+ data->status_checked = true;
+}
+
+static void init_test_conditions(struct test_data *data)
+{
+ hal_cb_init(data);
+ mgmt_cb_init(data);
+ expected_status_init(data);
+}
+
+static void check_expected_status(uint8_t status)
+{
+ struct test_data *data = tester_get_data();
+
+ if (data->test_data->expected_adapter_status == status)
+ data->status_checked = true;
+ else
+ tester_test_failed();
+
+ test_update_state();
+}
+
static int get_expected_hal_cb(void)
{
struct test_data *data = tester_get_data();
+ if (!(g_slist_length(data->expected_callbacks)))
+ return adapter_test_setup_mode;
+
return GPOINTER_TO_INT(data->expected_callbacks->data);
}
@@ -359,13 +395,28 @@ failed:
static void adapter_state_changed_cb(bt_state_t state)
{
- switch (get_expected_hal_cb()) {
+ enum hal_bluetooth_callbacks_id hal_cb;
+
+ hal_cb = get_expected_hal_cb();
+
+ switch (hal_cb) {
case adapter_state_changed_on:
if (state == BT_STATE_ON)
remove_expected_hal_cb();
else
tester_test_failed();
break;
+ case adapter_state_changed_off:
+ if (state == BT_STATE_OFF)
+ remove_expected_hal_cb();
+ else
+ tester_test_failed();
+ break;
+ case adapter_test_setup_mode:
+ if (state == BT_STATE_ON)
+ tester_setup_complete();
+ else
+ tester_setup_failed();
default:
break;
}
@@ -379,6 +430,10 @@ static void adapter_properties_cb(bt_status_t status, int num_properties,
for (i = 0; i < num_properties; i++) {
hal_cb = get_expected_hal_cb();
+
+ if (hal_cb == adapter_test_setup_mode)
+ break;
+
switch (properties[i].type) {
case BT_PROPERTY_BDADDR:
if (hal_cb != adapter_prop_bdaddr) {
@@ -454,6 +509,15 @@ static const struct generic_data bluetooth_enable_success_test = {
adapter_test_end}
};
+static const struct generic_data bluetooth_enable_done_test = {
+ .expected_hal_callbacks = {adapter_props, adapter_test_end},
+ .expected_adapter_status = BT_STATUS_DONE
+};
+
+static const struct generic_data bluetooth_disable_success_test = {
+ .expected_hal_callbacks = {adapter_state_changed_off, adapter_test_end}
+};
+
static bt_callbacks_t bt_callbacks = {
.size = sizeof(bt_callbacks),
.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -551,6 +615,15 @@ static void setup_base(const void *test_data)
tester_setup_complete();
}
+static void setup_enabled_adapter(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ setup(data);
+
+ data->if_bluetooth->enable();
+}
+
static void teardown(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -573,12 +646,31 @@ static void test_enable(const void *test_data)
{
struct test_data *data = tester_get_data();
- hal_cb_init(data);
- mgmt_cb_init(data);
+ init_test_conditions(data);
data->if_bluetooth->enable();
}
+static void test_enable_done(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ bt_status_t adapter_status;
+
+ init_test_conditions(data);
+
+ adapter_status = data->if_bluetooth->enable();
+ check_expected_status(adapter_status);
+}
+
+static void test_disable(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ init_test_conditions(data);
+
+ data->if_bluetooth->disable();
+}
+
static void controller_setup(const void *test_data)
{
tester_test_passed();
@@ -608,5 +700,11 @@ int main(int argc, char *argv[])
test_bredrle("Test Enable - Success", &bluetooth_enable_success_test,
setup_base, test_enable, teardown);
+ test_bredrle("Test Enable - Done", &bluetooth_enable_done_test,
+ setup_enabled_adapter, test_enable_done, teardown);
+
+ test_bredrle("Test Disable - Success", &bluetooth_disable_success_test,
+ setup_enabled_adapter, test_disable, teardown);
+
return tester_run();
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 6/7] android/tester: Add basic enable test
From: Marcin Kraglak @ 2013-12-11 10:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Grzegorz Kolodziejczyk
In-Reply-To: <1386758797-1809-1-git-send-email-marcin.kraglak@tieto.com>
From: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>
---
android/android-tester.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 225 insertions(+), 2 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 15f8c61..0dc1edf 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -35,7 +35,32 @@
#include <hardware/hardware.h>
#include <hardware/bluetooth.h>
+#define adapter_props adapter_prop_bdaddr, adapter_prop_bdname, \
+ adapter_prop_uuids, adapter_prop_cod, \
+ adapter_prop_scan_mode, adapter_prop_disc_timeout
+
+/*
+ * those are assigned to HAL methods and callbacks, we use ID later
+ * on mapped in switch-case due to different functions prototypes.
+ */
+
+enum hal_bluetooth_callbacks_id {
+ adapter_test_end,
+ adapter_state_changed_on,
+ adapter_state_changed_off,
+ adapter_prop_bdaddr,
+ adapter_prop_bdname,
+ adapter_prop_uuids,
+ adapter_prop_cod,
+ adapter_prop_scan_mode,
+ adapter_prop_disc_timeout,
+ adapter_prop_service_record,
+ adapter_prop_bonded_devices
+};
+
struct generic_data {
+ uint32_t expect_settings_set;
+ uint8_t expected_hal_callbacks[];
};
#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
@@ -44,15 +69,100 @@ struct generic_data {
struct test_data {
struct mgmt *mgmt;
uint16_t mgmt_index;
+ unsigned int mgmt_settings_id;
struct hciemu *hciemu;
enum hciemu_type hciemu_type;
const struct generic_data *test_data;
pid_t bluetoothd_pid;
const bt_interface_t *if_bluetooth;
+
+ bool mgmt_settings_set;
+ bool hal_cb_called;
+
+ GSList *expected_callbacks;
};
static char exec_dir[PATH_MAX + 1];
+static void test_update_state(void)
+{
+ struct test_data *data = tester_get_data();
+
+ if (data->mgmt_settings_set && data->hal_cb_called)
+ tester_test_passed();
+}
+
+static void test_mgmt_settings_set(struct test_data *data)
+{
+ data->mgmt_settings_set = true;
+
+ test_update_state();
+}
+
+static void command_generic_new_settings(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ uint32_t settings;
+
+ if (length != 4) {
+ tester_warn("Invalid parameter size for new settings event");
+ tester_test_failed();
+ return;
+ }
+
+ settings = bt_get_le32(param);
+
+ if ((settings & data->test_data->expect_settings_set) !=
+ data->test_data->expect_settings_set)
+ return;
+
+ test_mgmt_settings_set(data);
+ mgmt_unregister(data->mgmt, data->mgmt_settings_id);
+}
+
+static void hal_cb_init(struct test_data *data)
+{
+ unsigned int i = 0;
+
+ while (data->test_data->expected_hal_callbacks[i]) {
+ data->expected_callbacks =
+ g_slist_append(data->expected_callbacks,
+ GINT_TO_POINTER(data->test_data->expected_hal_callbacks[i]));
+ i++;
+ }
+}
+
+static void mgmt_cb_init(struct test_data *data)
+{
+ if (!data->test_data->expect_settings_set)
+ test_mgmt_settings_set(data);
+ else
+ data->mgmt_settings_id = mgmt_register(data->mgmt,
+ MGMT_EV_NEW_SETTINGS, data->mgmt_index,
+ command_generic_new_settings, NULL, NULL);
+}
+
+static int get_expected_hal_cb(void)
+{
+ struct test_data *data = tester_get_data();
+
+ return GPOINTER_TO_INT(data->expected_callbacks->data);
+}
+
+static void remove_expected_hal_cb(void)
+{
+ struct test_data *data = tester_get_data();
+
+ data->expected_callbacks = g_slist_remove(data->expected_callbacks,
+ data->expected_callbacks->data);
+
+ if (!data->expected_callbacks)
+ data->hal_cb_called = true;
+
+ test_update_state();
+}
+
static void read_info_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -247,10 +357,107 @@ failed:
close(fd);
}
+static void adapter_state_changed_cb(bt_state_t state)
+{
+ switch (get_expected_hal_cb()) {
+ case adapter_state_changed_on:
+ if (state == BT_STATE_ON)
+ remove_expected_hal_cb();
+ else
+ tester_test_failed();
+ break;
+ default:
+ break;
+ }
+}
+
+static void adapter_properties_cb(bt_status_t status, int num_properties,
+ bt_property_t *properties)
+{
+ enum hal_bluetooth_callbacks_id hal_cb;
+ int i;
+
+ for (i = 0; i < num_properties; i++) {
+ hal_cb = get_expected_hal_cb();
+ switch (properties[i].type) {
+ case BT_PROPERTY_BDADDR:
+ if (hal_cb != adapter_prop_bdaddr) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_BDNAME:
+ if (hal_cb != adapter_prop_bdname) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_UUIDS:
+ if (hal_cb != adapter_prop_uuids) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_CLASS_OF_DEVICE:
+ if (hal_cb != adapter_prop_cod) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_TYPE_OF_DEVICE:
+ if (hal_cb != adapter_prop_bdaddr) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_SERVICE_RECORD:
+ if (hal_cb != adapter_prop_service_record) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_ADAPTER_SCAN_MODE:
+ if (hal_cb != adapter_prop_scan_mode) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
+ if (hal_cb != adapter_prop_bonded_devices) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ if (hal_cb != adapter_prop_disc_timeout) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static const struct generic_data bluetooth_enable_success_test = {
+ .expected_hal_callbacks = {adapter_props, adapter_state_changed_on,
+ adapter_test_end}
+};
+
static bt_callbacks_t bt_callbacks = {
.size = sizeof(bt_callbacks),
- .adapter_state_changed_cb = NULL,
- .adapter_properties_cb = NULL,
+ .adapter_state_changed_cb = adapter_state_changed_cb,
+ .adapter_properties_cb = adapter_properties_cb,
.remote_device_properties_cb = NULL,
.device_found_cb = NULL,
.discovery_state_changed_cb = NULL,
@@ -356,9 +563,22 @@ static void teardown(const void *test_data)
if (data->bluetoothd_pid)
waitpid(data->bluetoothd_pid, NULL, 0);
+ if (data->expected_callbacks)
+ g_slist_free(data->expected_callbacks);
+
tester_teardown_complete();
}
+static void test_enable(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ hal_cb_init(data);
+ mgmt_cb_init(data);
+
+ data->if_bluetooth->enable();
+}
+
static void controller_setup(const void *test_data)
{
tester_test_passed();
@@ -385,5 +605,8 @@ int main(int argc, char *argv[])
test_bredrle("Test Init", NULL, setup_base, controller_setup, teardown);
+ test_bredrle("Test Enable - Success", &bluetooth_enable_success_test,
+ setup_base, test_enable, teardown);
+
return tester_run();
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 5/7] android/tester: Make HAL logging wrapper print to stderr instead of stdout
From: Marcin Kraglak @ 2013-12-11 10:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386758797-1809-1-git-send-email-marcin.kraglak@tieto.com>
From: Szymon Janc <szymon.janc@tieto.com>
This is used for testing and for user it makes no difference. This
will allow to switch on/off verbose logging from automated android
tester.
---
android/hal-log.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/android/hal-log.h b/android/hal-log.h
index 9bd024d..63ff61b 100644
--- a/android/hal-log.h
+++ b/android/hal-log.h
@@ -25,7 +25,7 @@
#define LOG_WARN " W"
#define LOG_ERROR " E"
#define LOG_DEBUG " D"
-#define ALOG(pri, tag, fmt, arg...) printf(tag pri": " fmt"\n", ##arg)
+#define ALOG(pri, tag, fmt, arg...) fprintf(stderr, tag pri": " fmt"\n", ##arg)
#endif
#define info(fmt, arg...) ALOG(LOG_INFO, LOG_TAG, fmt, ##arg)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 4/7] android/tester: Add stack initialization of stack in setup
From: Marcin Kraglak @ 2013-12-11 10:46 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386758797-1809-1-git-send-email-marcin.kraglak@tieto.com>
This add stack initialization and cleanup in setup/teardown.
---
android/Makefile.am | 10 +++++++--
android/android-tester.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/android/Makefile.am b/android/Makefile.am
index 5364c2e..f3e77c3 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -91,9 +91,15 @@ android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
src/shared/tester.h src/shared/tester.c \
- android/android-tester.c
+ android/hal-utils.h android/hal-utils.c \
+ android/client/hwmodule.c android/android-tester.c
-android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+android_android_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_android_tester_LDADD = lib/libbluetooth-internal.la \
+ android/libhal-internal.la @GLIB_LIBS@
+
+android_android_tester_LDFLAGS = -pthread
endif
diff --git a/android/android-tester.c b/android/android-tester.c
index ad7aa39..15f8c61 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -32,6 +32,9 @@
#include "src/shared/mgmt.h"
#include "src/shared/hciemu.h"
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+
struct generic_data {
};
@@ -45,6 +48,7 @@ struct test_data {
enum hciemu_type hciemu_type;
const struct generic_data *test_data;
pid_t bluetoothd_pid;
+ const bt_interface_t *if_bluetooth;
};
static char exec_dir[PATH_MAX + 1];
@@ -243,12 +247,32 @@ failed:
close(fd);
}
+static bt_callbacks_t bt_callbacks = {
+ .size = sizeof(bt_callbacks),
+ .adapter_state_changed_cb = NULL,
+ .adapter_properties_cb = NULL,
+ .remote_device_properties_cb = NULL,
+ .device_found_cb = NULL,
+ .discovery_state_changed_cb = NULL,
+ .pin_request_cb = NULL,
+ .ssp_request_cb = NULL,
+ .bond_state_changed_cb = NULL,
+ .acl_state_changed_cb = NULL,
+ .thread_evt_cb = NULL,
+ .dut_mode_recv_cb = NULL,
+ .le_test_mode_cb = NULL
+};
+
static void setup(struct test_data *data)
{
+ const hw_module_t *module;
+ hw_device_t *device;
+ bt_status_t status;
int signal_fd[2];
char buf[1024];
pid_t pid;
int len;
+ int err;
if (pipe(signal_fd)) {
tester_setup_failed();
@@ -282,6 +306,33 @@ static void setup(struct test_data *data)
tester_setup_failed();
return;
}
+
+ close(signal_fd[0]);
+
+ err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+ if (err) {
+ tester_setup_failed();
+ return;
+ }
+
+ err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+ if (err) {
+ tester_setup_failed();
+ return;
+ }
+
+ data->if_bluetooth = ((bluetooth_device_t *)
+ device)->get_bluetooth_interface();
+ if (!data->if_bluetooth) {
+ tester_setup_failed();
+ return;
+ }
+
+ status = data->if_bluetooth->init(&bt_callbacks);
+ if (status != BT_STATUS_SUCCESS) {
+ data->if_bluetooth = NULL;
+ tester_setup_failed();
+ }
}
static void setup_base(const void *test_data)
@@ -297,6 +348,11 @@ static void teardown(const void *test_data)
{
struct test_data *data = tester_get_data();
+ if (data->if_bluetooth) {
+ data->if_bluetooth->cleanup();
+ data->if_bluetooth = NULL;
+ }
+
if (data->bluetoothd_pid)
waitpid(data->bluetoothd_pid, NULL, 0);
@@ -305,6 +361,7 @@ static void teardown(const void *test_data)
static void controller_setup(const void *test_data)
{
+ tester_test_passed();
}
#define test_bredrle(name, data, test_setup, test, test_teardown) \
--
1.8.3.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox