Stateless decompression mode 3 combines the MAC address from the MAC header
with link-local prefix FE80::/64 to reconstruct the original IPv6 address.
This patch corrects comments, variable llconf and lowpan_uncompress_addr
to be compatible with RFC 4644.

Signed-off-by: Ralph Droms <rdr...@cisco.com>
---
 net/ieee802154/6lowpan.c |   50 +++++++++++++++++++++++++++------------------
 1 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 55e1fd5..a7bac63 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -68,32 +68,32 @@ static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
 static LIST_HEAD(lowpan_devices);
 
 /*
- * Uncompression of linklocal:
+ * Uncompression of stateless unicast:
  *   0 -> 16 bytes from packet
  *   1 -> 2  bytes from prefix - bunch of zeroes and 8 from packet
  *   2 -> 2  bytes from prefix - zeroes + 2 from packet
- *   3 -> 2  bytes from prefix - infer 8 bytes from lladdr
+ *   3 -> 2  bytes from prefix - IID == MAC
  *
  *  NOTE: => the uncompress function does change 0xf to 0x10
  *  NOTE: 0x00 => no-autoconfig => unspecified
  */
-static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
+static const u8 lowpan_unc_slconf[] = {0x0f, 0x28, 0x22, 0x20};
 
 /*
  * Uncompression of ctx-based:
  *   0 -> 0 bits  from packet [unspecified / reserved]
  *   1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet
  *   2 -> 8 bytes from prefix - zeroes + 2 from packet
- *   3 -> 8 bytes from prefix - infer 8 bytes from lladdr
+ *   3 -> 8 bytes from prefix - IID == MAC
  */
 static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
 
 /*
- * Uncompression of ctx-base
+ * Uncompression of stateless multicast:
  *   0 -> 0 bits from packet
  *   1 -> 2 bytes from prefix - bunch of zeroes 5 from packet
  *   2 -> 2 bytes from prefix - zeroes + 3 from packet
- *   3 -> 2 bytes from prefix - infer 1 bytes from lladdr
+ *   3 -> 2 bytes from prefix - infer 1 bytes from MAC
  */
 static const u8 lowpan_unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
 
@@ -208,7 +208,7 @@ lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, 
unsigned char *lladdr)
  */
 static int
 lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
-       u8 const *prefix, u8 pref_post_count, unsigned char *lladdr)
+       u8 const *prefix, u8 pref_post_count, unsigned char *macaddr)
 {
        u8 prefcount = pref_post_count >> 4;
        u8 postcount = pref_post_count & 0x0f;
@@ -217,9 +217,9 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr 
*ipaddr,
        prefcount = (prefcount == 15 ? 16 : prefcount);
        postcount = (postcount == 15 ? 16 : postcount);
 
-       if (lladdr)
+       if (macaddr)
                lowpan_raw_dump_inline(__func__, "linklocal address",
-                                               lladdr, IEEE802154_ADDR_LEN);
+                                               macaddr, IEEE802154_ADDR_LEN);
        if (prefcount > 0)
                memcpy(ipaddr, prefix, prefcount);
 
@@ -231,11 +231,11 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct 
in6_addr *ipaddr,
                memcpy(&ipaddr->s6_addr[16 - postcount], skb->data, postcount);
                skb_pull(skb, postcount);
        } else if (prefcount > 0) {
-               if (lladdr == NULL)
+               if (macaddr == NULL)
                        return -EINVAL;
 
                /* no IID based configuration if no prefix and no data */
-               lowpan_uip_ds6_set_addr_iid(ipaddr, lladdr);
+               lowpan_uip_ds6_set_addr_iid(ipaddr, macaddr);
        }
 
        pr_debug("uncompressing %d + %d => ", prefcount, postcount);
@@ -916,24 +916,34 @@ lowpan_process_data(struct sk_buff *skb)
        tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
 
        /* Source address uncompression */
-       pr_debug("source address stateless compression\n");
-       err = lowpan_uncompress_addr(skb, &hdr.saddr, lowpan_llprefix,
-                               lowpan_unc_llconf[tmp], skb->data);
-       if (err)
+       pr_debug("source address uncompression - SAM %d\n", tmp);
+       if (iphc1 & LOWPAN_IPHC_SAC) {
+               pr_debug("stateful source uncompression not implemented\n");
                goto drop;
+       } else {
+               pr_debug("stateless source uncompression\n");
+               err = lowpan_uncompress_addr(skb, &hdr.saddr, lowpan_llprefix,
+                                       lowpan_unc_slconf[tmp], skb->data);
+               if (err)
+                       goto drop;
+       }
 
        /* Extract DAM to the tmp variable */
        tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
 
+       /* destination address uncompression */
+       pr_debug("source address uncompression - M %d, DAM %d\n",
+                iphc1 & LOWPAN_IPHC_M, tmp);
+
        /* 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 */
+                       pr_debug("context-based mcast uncompression not 
implemented\n");
+                       /* TODO: implement this; does not depend on contex 
distribution */
                } else {
                        u8 prefix[] = {0xff, 0x02};
 
-                       pr_debug("dest: non context-based mcast compression\n");
+                       pr_debug("stateless mcast uncompression\n");
                        if (0 < tmp && tmp < 3) {
                                if (lowpan_fetch_skb_u8(skb, &prefix[1]))
                                        goto drop;
@@ -945,9 +955,9 @@ lowpan_process_data(struct sk_buff *skb)
                                goto drop;
                }
        } else {
-               pr_debug("dest: stateless compression\n");
+               pr_debug("stateless compression\n");
                err = lowpan_uncompress_addr(skb, &hdr.daddr, lowpan_llprefix,
-                               lowpan_unc_llconf[tmp], skb->data);
+                               lowpan_unc_slconf[tmp], skb->data);
                if (err)
                        goto drop;
        }
-- 
1.7.7.6


------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to