aboutsummaryrefslogtreecommitdiffstats
path: root/net/6lowpan/iphc.c
diff options
context:
space:
mode:
authorAlexander Aring <aar@pengutronix.de>2016-02-22 03:13:54 -0500
committerMarcel Holtmann <marcel@holtmann.org>2016-02-23 14:29:40 -0500
commit5609c185f24dffca5f6a9c127106869da150be03 (patch)
tree709e278dc1463646bf0db64b2f03511e3e4ec934 /net/6lowpan/iphc.c
parentaef00c15b8c503083a703900a755fdb1cf2436e0 (diff)
6lowpan: iphc: add support for stateful compression
This patch introduce support for IPHC stateful address compression. It will offer the context table via one debugfs entry. This debugfs has and directory for each cid entry for the context table. Inside each cid directory there exists the following files: - "active": If the entry is added or deleted. The context table is original a list implementation, this flag will indicate if the context is part of list or not. - "prefix": The ipv6 prefix. - "prefix_length": The prefix length for the prefix. - "compression": The compression flag according RFC6775. This part should be moved into sysfs after some testing time. Also the debugfs entry contains a "show" file which is a pretty-printout for the current context table information. Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com> Signed-off-by: Alexander Aring <aar@pengutronix.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/6lowpan/iphc.c')
-rw-r--r--net/6lowpan/iphc.c414
1 files changed, 357 insertions, 57 deletions
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 346b5c1a9185..d2a565cde4f4 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -56,6 +56,7 @@
56/* special link-layer handling */ 56/* special link-layer handling */
57#include <net/mac802154.h> 57#include <net/mac802154.h>
58 58
59#include "6lowpan_i.h"
59#include "nhc.h" 60#include "nhc.h"
60 61
61/* Values of fields within the IPHC encoding first byte */ 62/* Values of fields within the IPHC encoding first byte */
@@ -147,6 +148,9 @@
147 (((a)->s6_addr16[6]) == 0) && \ 148 (((a)->s6_addr16[6]) == 0) && \
148 (((a)->s6_addr[14]) == 0)) 149 (((a)->s6_addr[14]) == 0))
149 150
151#define LOWPAN_IPHC_CID_DCI(cid) (cid & 0x0f)
152#define LOWPAN_IPHC_CID_SCI(cid) ((cid & 0xf0) >> 4)
153
150static inline void iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr, 154static inline void iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr,
151 const void *lladdr) 155 const void *lladdr)
152{ 156{
@@ -195,6 +199,98 @@ static inline void iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr,
195 } 199 }
196} 200}
197 201
202static struct lowpan_iphc_ctx *
203lowpan_iphc_ctx_get_by_id(const struct net_device *dev, u8 id)
204{
205 struct lowpan_iphc_ctx *ret = &lowpan_priv(dev)->ctx.table[id];
206
207 if (!lowpan_iphc_ctx_is_active(ret))
208 return NULL;
209
210 return ret;
211}
212
213static struct lowpan_iphc_ctx *
214lowpan_iphc_ctx_get_by_addr(const struct net_device *dev,
215 const struct in6_addr *addr)
216{
217 struct lowpan_iphc_ctx *table = lowpan_priv(dev)->ctx.table;
218 struct lowpan_iphc_ctx *ret = NULL;
219 struct in6_addr addr_pfx;
220 u8 addr_plen;
221 int i;
222
223 for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
224 /* Check if context is valid. A context that is not valid
225 * MUST NOT be used for compression.
226 */
227 if (!lowpan_iphc_ctx_is_active(&table[i]) ||
228 !lowpan_iphc_ctx_is_compression(&table[i]))
229 continue;
230
231 ipv6_addr_prefix(&addr_pfx, addr, table[i].plen);
232
233 /* if prefix len < 64, the remaining bits until 64th bit is
234 * zero. Otherwise we use table[i]->plen.
235 */
236 if (table[i].plen < 64)
237 addr_plen = 64;
238 else
239 addr_plen = table[i].plen;
240
241 if (ipv6_prefix_equal(&addr_pfx, &table[i].pfx, addr_plen)) {
242 /* remember first match */
243 if (!ret) {
244 ret = &table[i];
245 continue;
246 }
247
248 /* get the context with longest prefix len */
249 if (table[i].plen > ret->plen)
250 ret = &table[i];
251 }
252 }
253
254 return ret;
255}
256
257static struct lowpan_iphc_ctx *
258lowpan_iphc_ctx_get_by_mcast_addr(const struct net_device *dev,
259 const struct in6_addr *addr)
260{
261 struct lowpan_iphc_ctx *table = lowpan_priv(dev)->ctx.table;
262 struct lowpan_iphc_ctx *ret = NULL;
263 struct in6_addr addr_mcast, network_pfx = {};
264 int i;
265
266 /* init mcast address with */
267 memcpy(&addr_mcast, addr, sizeof(*addr));
268
269 for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
270 /* Check if context is valid. A context that is not valid
271 * MUST NOT be used for compression.
272 */
273 if (!lowpan_iphc_ctx_is_active(&table[i]) ||
274 !lowpan_iphc_ctx_is_compression(&table[i]))
275 continue;
276
277 /* setting plen */
278 addr_mcast.s6_addr[3] = table[i].plen;
279 /* get network prefix to copy into multicast address */
280 ipv6_addr_prefix(&network_pfx, &table[i].pfx,
281 table[i].plen);
282 /* setting network prefix */
283 memcpy(&addr_mcast.s6_addr[4], &network_pfx, 8);
284
285 if (ipv6_addr_equal(addr, &addr_mcast)) {
286 ret = &table[i];
287 break;
288 }
289 }
290
291 return ret;
292}
293
198/* Uncompress address function for source and 294/* Uncompress address function for source and
199 * destination address(non-multicast). 295 * destination address(non-multicast).
200 * 296 *
@@ -259,30 +355,59 @@ static int uncompress_addr(struct sk_buff *skb, const struct net_device *dev,
259/* Uncompress address function for source context 355/* Uncompress address function for source context
260 * based address(non-multicast). 356 * based address(non-multicast).
261 */ 357 */
262static int uncompress_context_based_src_addr(struct sk_buff *skb, 358static int uncompress_ctx_addr(struct sk_buff *skb,
263 struct in6_addr *ipaddr, 359 const struct net_device *dev,
264 u8 address_mode) 360 const struct lowpan_iphc_ctx *ctx,
361 struct in6_addr *ipaddr, u8 address_mode,
362 const void *lladdr)
265{ 363{
364 bool fail;
365
266 switch (address_mode) { 366 switch (address_mode) {
267 case LOWPAN_IPHC_SAM_00: 367 /* SAM and DAM are the same here */
268 /* unspec address :: 368 case LOWPAN_IPHC_DAM_00:
369 fail = false;
370 /* SAM_00 -> unspec address ::
269 * Do nothing, address is already :: 371 * Do nothing, address is already ::
372 *
373 * DAM 00 -> reserved should never occur.
270 */ 374 */
271 break; 375 break;
272 case LOWPAN_IPHC_SAM_01: 376 case LOWPAN_IPHC_SAM_01:
273 /* TODO */ 377 case LOWPAN_IPHC_DAM_01:
378 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
379 ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
380 break;
274 case LOWPAN_IPHC_SAM_10: 381 case LOWPAN_IPHC_SAM_10:
275 /* TODO */ 382 case LOWPAN_IPHC_DAM_10:
383 ipaddr->s6_addr[11] = 0xFF;
384 ipaddr->s6_addr[12] = 0xFE;
385 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
386 ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
387 break;
276 case LOWPAN_IPHC_SAM_11: 388 case LOWPAN_IPHC_SAM_11:
277 /* TODO */ 389 case LOWPAN_IPHC_DAM_11:
278 netdev_warn(skb->dev, "SAM value 0x%x not supported\n", 390 fail = false;
279 address_mode); 391 switch (lowpan_priv(dev)->lltype) {
280 return -EINVAL; 392 case LOWPAN_LLTYPE_IEEE802154:
393 iphc_uncompress_802154_lladdr(ipaddr, lladdr);
394 break;
395 default:
396 iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
397 break;
398 }
399 ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
400 break;
281 default: 401 default:
282 pr_debug("Invalid sam value: 0x%x\n", address_mode); 402 pr_debug("Invalid sam value: 0x%x\n", address_mode);
283 return -EINVAL; 403 return -EINVAL;
284 } 404 }
285 405
406 if (fail) {
407 pr_debug("Failed to fetch skb data\n");
408 return -EIO;
409 }
410
286 raw_dump_inline(NULL, 411 raw_dump_inline(NULL,
287 "Reconstructed context based ipv6 src addr is", 412 "Reconstructed context based ipv6 src addr is",
288 ipaddr->s6_addr, 16); 413 ipaddr->s6_addr, 16);
@@ -346,6 +471,30 @@ static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
346 return 0; 471 return 0;
347} 472}
348 473
474static int lowpan_uncompress_multicast_ctx_daddr(struct sk_buff *skb,
475 struct lowpan_iphc_ctx *ctx,
476 struct in6_addr *ipaddr,
477 u8 address_mode)
478{
479 struct in6_addr network_pfx = {};
480 bool fail;
481
482 ipaddr->s6_addr[0] = 0xFF;
483 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 2);
484 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[12], 4);
485 if (fail < 0)
486 return -EIO;
487
488 /* take prefix_len and network prefix from the context */
489 ipaddr->s6_addr[3] = ctx->plen;
490 /* get network prefix to copy into multicast address */
491 ipv6_addr_prefix(&network_pfx, &ctx->pfx, ctx->plen);
492 /* setting network prefix */
493 memcpy(&ipaddr->s6_addr[4], &network_pfx, 8);
494
495 return 0;
496}
497
349/* get the ecn values from iphc tf format and set it to ipv6hdr */ 498/* get the ecn values from iphc tf format and set it to ipv6hdr */
350static inline void lowpan_iphc_tf_set_ecn(struct ipv6hdr *hdr, const u8 *tf) 499static inline void lowpan_iphc_tf_set_ecn(struct ipv6hdr *hdr, const u8 *tf)
351{ 500{
@@ -459,7 +608,8 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
459 const void *daddr, const void *saddr) 608 const void *daddr, const void *saddr)
460{ 609{
461 struct ipv6hdr hdr = {}; 610 struct ipv6hdr hdr = {};
462 u8 iphc0, iphc1; 611 struct lowpan_iphc_ctx *ci;
612 u8 iphc0, iphc1, cid = 0;
463 int err; 613 int err;
464 614
465 raw_dump_table(__func__, "raw skb data dump uncompressed", 615 raw_dump_table(__func__, "raw skb data dump uncompressed",
@@ -469,12 +619,14 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
469 lowpan_fetch_skb(skb, &iphc1, sizeof(iphc1))) 619 lowpan_fetch_skb(skb, &iphc1, sizeof(iphc1)))
470 return -EINVAL; 620 return -EINVAL;
471 621
472 /* another if the CID flag is set */
473 if (iphc1 & LOWPAN_IPHC_CID)
474 return -ENOTSUPP;
475
476 hdr.version = 6; 622 hdr.version = 6;
477 623
624 /* default CID = 0, another if the CID flag is set */
625 if (iphc1 & LOWPAN_IPHC_CID) {
626 if (lowpan_fetch_skb(skb, &cid, sizeof(cid)))
627 return -EINVAL;
628 }
629
478 err = lowpan_iphc_tf_decompress(skb, &hdr, 630 err = lowpan_iphc_tf_decompress(skb, &hdr,
479 iphc0 & LOWPAN_IPHC_TF_MASK); 631 iphc0 & LOWPAN_IPHC_TF_MASK);
480 if (err < 0) 632 if (err < 0)
@@ -500,10 +652,17 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
500 } 652 }
501 653
502 if (iphc1 & LOWPAN_IPHC_SAC) { 654 if (iphc1 & LOWPAN_IPHC_SAC) {
503 /* Source address context based uncompression */ 655 spin_lock_bh(&lowpan_priv(dev)->ctx.lock);
656 ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_SCI(cid));
657 if (!ci) {
658 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
659 return -EINVAL;
660 }
661
504 pr_debug("SAC bit is set. Handle context based source address.\n"); 662 pr_debug("SAC bit is set. Handle context based source address.\n");
505 err = uncompress_context_based_src_addr(skb, &hdr.saddr, 663 err = uncompress_ctx_addr(skb, dev, ci, &hdr.saddr,
506 iphc1 & LOWPAN_IPHC_SAM_MASK); 664 iphc1 & LOWPAN_IPHC_SAM_MASK, saddr);
665 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
507 } else { 666 } else {
508 /* Source address uncompression */ 667 /* Source address uncompression */
509 pr_debug("source address stateless compression\n"); 668 pr_debug("source address stateless compression\n");
@@ -515,27 +674,52 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
515 if (err) 674 if (err)
516 return -EINVAL; 675 return -EINVAL;
517 676
518 /* check for Multicast Compression */ 677 switch (iphc1 & (LOWPAN_IPHC_M | LOWPAN_IPHC_DAC)) {
519 if (iphc1 & LOWPAN_IPHC_M) { 678 case LOWPAN_IPHC_M | LOWPAN_IPHC_DAC:
520 if (iphc1 & LOWPAN_IPHC_DAC) { 679 spin_lock_bh(&lowpan_priv(dev)->ctx.lock);
521 pr_debug("dest: context-based mcast compression\n"); 680 ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_DCI(cid));
522 /* TODO: implement this */ 681 if (!ci) {
523 } else { 682 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
524 err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr, 683 return -EINVAL;
525 iphc1 & LOWPAN_IPHC_DAM_MASK); 684 }
526 685
527 if (err) 686 /* multicast with context */
528 return -EINVAL; 687 pr_debug("dest: context-based mcast compression\n");
688 err = lowpan_uncompress_multicast_ctx_daddr(skb, ci,
689 &hdr.daddr,
690 iphc1 & LOWPAN_IPHC_DAM_MASK);
691 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
692 break;
693 case LOWPAN_IPHC_M:
694 /* multicast */
695 err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
696 iphc1 & LOWPAN_IPHC_DAM_MASK);
697 break;
698 case LOWPAN_IPHC_DAC:
699 spin_lock_bh(&lowpan_priv(dev)->ctx.lock);
700 ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_DCI(cid));
701 if (!ci) {
702 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
703 return -EINVAL;
529 } 704 }
530 } else { 705
706 /* Destination address context based uncompression */
707 pr_debug("DAC bit is set. Handle context based destination address.\n");
708 err = uncompress_ctx_addr(skb, dev, ci, &hdr.daddr,
709 iphc1 & LOWPAN_IPHC_DAM_MASK, daddr);
710 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
711 break;
712 default:
531 err = uncompress_addr(skb, dev, &hdr.daddr, 713 err = uncompress_addr(skb, dev, &hdr.daddr,
532 iphc1 & LOWPAN_IPHC_DAM_MASK, daddr); 714 iphc1 & LOWPAN_IPHC_DAM_MASK, daddr);
533 pr_debug("dest: stateless compression mode %d dest %pI6c\n", 715 pr_debug("dest: stateless compression mode %d dest %pI6c\n",
534 iphc1 & LOWPAN_IPHC_DAM_MASK, &hdr.daddr); 716 iphc1 & LOWPAN_IPHC_DAM_MASK, &hdr.daddr);
535 if (err) 717 break;
536 return -EINVAL;
537 } 718 }
538 719
720 if (err)
721 return -EINVAL;
722
539 /* Next header data uncompression */ 723 /* Next header data uncompression */
540 if (iphc0 & LOWPAN_IPHC_NH) { 724 if (iphc0 & LOWPAN_IPHC_NH) {
541 err = lowpan_nhc_do_uncompression(skb, dev, &hdr); 725 err = lowpan_nhc_do_uncompression(skb, dev, &hdr);
@@ -585,6 +769,58 @@ static const u8 lowpan_iphc_dam_to_sam_value[] = {
585 [LOWPAN_IPHC_DAM_11] = LOWPAN_IPHC_SAM_11, 769 [LOWPAN_IPHC_DAM_11] = LOWPAN_IPHC_SAM_11,
586}; 770};
587 771
772static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct in6_addr *ipaddr,
773 const struct lowpan_iphc_ctx *ctx,
774 const unsigned char *lladdr, bool sam)
775{
776 struct in6_addr tmp = {};
777 u8 dam;
778
779 /* check for SAM/DAM = 11 */
780 memcpy(&tmp.s6_addr[8], lladdr, 8);
781 /* second bit-flip (Universe/Local) is done according RFC2464 */
782 tmp.s6_addr[8] ^= 0x02;
783 /* context information are always used */
784 ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
785 if (ipv6_addr_equal(&tmp, ipaddr)) {
786 dam = LOWPAN_IPHC_DAM_11;
787 goto out;
788 }
789
790 memset(&tmp, 0, sizeof(tmp));
791 /* check for SAM/DAM = 01 */
792 tmp.s6_addr[11] = 0xFF;
793 tmp.s6_addr[12] = 0xFE;
794 memcpy(&tmp.s6_addr[14], &ipaddr->s6_addr[14], 2);
795 /* context information are always used */
796 ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
797 if (ipv6_addr_equal(&tmp, ipaddr)) {
798 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[14], 2);
799 dam = LOWPAN_IPHC_DAM_10;
800 goto out;
801 }
802
803 memset(&tmp, 0, sizeof(tmp));
804 /* check for SAM/DAM = 10, should always match */
805 memcpy(&tmp.s6_addr[8], &ipaddr->s6_addr[8], 8);
806 /* context information are always used */
807 ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
808 if (ipv6_addr_equal(&tmp, ipaddr)) {
809 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[8], 8);
810 dam = LOWPAN_IPHC_DAM_01;
811 goto out;
812 }
813
814 WARN_ON_ONCE("context found but no address mode matched\n");
815 return -EINVAL;
816out:
817
818 if (sam)
819 return lowpan_iphc_dam_to_sam_value[dam];
820 else
821 return dam;
822}
823
588static u8 lowpan_compress_addr_64(u8 **hc_ptr, const struct in6_addr *ipaddr, 824static u8 lowpan_compress_addr_64(u8 **hc_ptr, const struct in6_addr *ipaddr,
589 const unsigned char *lladdr, bool sam) 825 const unsigned char *lladdr, bool sam)
590{ 826{
@@ -708,6 +944,21 @@ static u8 lowpan_iphc_tf_compress(u8 **hc_ptr, const struct ipv6hdr *hdr)
708 return val; 944 return val;
709} 945}
710 946
947static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
948 const struct lowpan_iphc_ctx *ctx,
949 const struct in6_addr *ipaddr)
950{
951 u8 data[6];
952
953 /* flags/scope, reserved (RIID) */
954 memcpy(data, &ipaddr->s6_addr[1], 2);
955 /* group ID */
956 memcpy(&data[1], &ipaddr->s6_addr[11], 4);
957 lowpan_push_hc_data(hc_ptr, data, 6);
958
959 return LOWPAN_IPHC_DAM_00;
960}
961
711static u8 lowpan_iphc_mcast_addr_compress(u8 **hc_ptr, 962static u8 lowpan_iphc_mcast_addr_compress(u8 **hc_ptr,
712 const struct in6_addr *ipaddr) 963 const struct in6_addr *ipaddr)
713{ 964{
@@ -742,10 +993,11 @@ static u8 lowpan_iphc_mcast_addr_compress(u8 **hc_ptr,
742int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev, 993int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
743 const void *daddr, const void *saddr) 994 const void *daddr, const void *saddr)
744{ 995{
745 u8 iphc0, iphc1, *hc_ptr; 996 u8 iphc0, iphc1, *hc_ptr, cid = 0;
746 struct ipv6hdr *hdr; 997 struct ipv6hdr *hdr;
747 u8 head[LOWPAN_IPHC_MAX_HC_BUF_LEN] = {}; 998 u8 head[LOWPAN_IPHC_MAX_HC_BUF_LEN] = {};
748 int ret, addr_type; 999 struct lowpan_iphc_ctx *dci, *sci, dci_entry, sci_entry;
1000 int ret, ipv6_daddr_type, ipv6_saddr_type;
749 1001
750 if (skb->protocol != htons(ETH_P_IPV6)) 1002 if (skb->protocol != htons(ETH_P_IPV6))
751 return -EINVAL; 1003 return -EINVAL;
@@ -769,14 +1021,38 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
769 iphc0 = LOWPAN_DISPATCH_IPHC; 1021 iphc0 = LOWPAN_DISPATCH_IPHC;
770 iphc1 = 0; 1022 iphc1 = 0;
771 1023
772 /* TODO: context lookup */
773
774 raw_dump_inline(__func__, "saddr", saddr, EUI64_ADDR_LEN); 1024 raw_dump_inline(__func__, "saddr", saddr, EUI64_ADDR_LEN);
775 raw_dump_inline(__func__, "daddr", daddr, EUI64_ADDR_LEN); 1025 raw_dump_inline(__func__, "daddr", daddr, EUI64_ADDR_LEN);
776 1026
777 raw_dump_table(__func__, "sending raw skb network uncompressed packet", 1027 raw_dump_table(__func__, "sending raw skb network uncompressed packet",
778 skb->data, skb->len); 1028 skb->data, skb->len);
779 1029
1030 ipv6_daddr_type = ipv6_addr_type(&hdr->daddr);
1031 spin_lock_bh(&lowpan_priv(dev)->ctx.lock);
1032 if (ipv6_daddr_type & IPV6_ADDR_MULTICAST)
1033 dci = lowpan_iphc_ctx_get_by_mcast_addr(dev, &hdr->daddr);
1034 else
1035 dci = lowpan_iphc_ctx_get_by_addr(dev, &hdr->daddr);
1036 if (dci) {
1037 memcpy(&dci_entry, dci, sizeof(*dci));
1038 cid |= dci->id;
1039 }
1040 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
1041
1042 spin_lock_bh(&lowpan_priv(dev)->ctx.lock);
1043 sci = lowpan_iphc_ctx_get_by_addr(dev, &hdr->saddr);
1044 if (sci) {
1045 memcpy(&sci_entry, sci, sizeof(*sci));
1046 cid |= (sci->id << 4);
1047 }
1048 spin_unlock_bh(&lowpan_priv(dev)->ctx.lock);
1049
1050 /* if cid is zero it will be compressed */
1051 if (cid) {
1052 iphc1 |= LOWPAN_IPHC_CID;
1053 lowpan_push_hc_data(&hc_ptr, &cid, sizeof(cid));
1054 }
1055
780 /* Traffic Class, Flow Label compression */ 1056 /* Traffic Class, Flow Label compression */
781 iphc0 |= lowpan_iphc_tf_compress(&hc_ptr, hdr); 1057 iphc0 |= lowpan_iphc_tf_compress(&hc_ptr, hdr);
782 1058
@@ -813,39 +1089,63 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
813 sizeof(hdr->hop_limit)); 1089 sizeof(hdr->hop_limit));
814 } 1090 }
815 1091
816 addr_type = ipv6_addr_type(&hdr->saddr); 1092 ipv6_saddr_type = ipv6_addr_type(&hdr->saddr);
817 /* source address compression */ 1093 /* source address compression */
818 if (addr_type == IPV6_ADDR_ANY) { 1094 if (ipv6_saddr_type == IPV6_ADDR_ANY) {
819 pr_debug("source address is unspecified, setting SAC\n"); 1095 pr_debug("source address is unspecified, setting SAC\n");
820 iphc1 |= LOWPAN_IPHC_SAC; 1096 iphc1 |= LOWPAN_IPHC_SAC;
821 } else { 1097 } else {
822 if (addr_type & IPV6_ADDR_LINKLOCAL) { 1098 if (sci) {
823 iphc1 |= lowpan_compress_addr_64(&hc_ptr, &hdr->saddr, 1099 iphc1 |= lowpan_compress_ctx_addr(&hc_ptr, &hdr->saddr,
824 saddr, true); 1100 &sci_entry, saddr,
825 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n", 1101 true);
826 &hdr->saddr, iphc1); 1102 iphc1 |= LOWPAN_IPHC_SAC;
827 } else { 1103 } else {
828 pr_debug("send the full source address\n"); 1104 if (ipv6_saddr_type & IPV6_ADDR_LINKLOCAL) {
829 lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16); 1105 iphc1 |= lowpan_compress_addr_64(&hc_ptr,
1106 &hdr->saddr,
1107 saddr, true);
1108 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
1109 &hdr->saddr, iphc1);
1110 } else {
1111 pr_debug("send the full source address\n");
1112 lowpan_push_hc_data(&hc_ptr,
1113 hdr->saddr.s6_addr, 16);
1114 }
830 } 1115 }
831 } 1116 }
832 1117
833 addr_type = ipv6_addr_type(&hdr->daddr);
834 /* destination address compression */ 1118 /* destination address compression */
835 if (addr_type & IPV6_ADDR_MULTICAST) { 1119 if (ipv6_daddr_type & IPV6_ADDR_MULTICAST) {
836 pr_debug("destination address is multicast: "); 1120 pr_debug("destination address is multicast: ");
837 iphc1 |= LOWPAN_IPHC_M; 1121 if (dci) {
838 iphc1 |= lowpan_iphc_mcast_addr_compress(&hc_ptr, &hdr->daddr); 1122 iphc1 |= lowpan_iphc_mcast_ctx_addr_compress(&hc_ptr,
1123 &dci_entry,
1124 &hdr->daddr);
1125 } else {
1126 iphc1 |= LOWPAN_IPHC_M;
1127 iphc1 |= lowpan_iphc_mcast_addr_compress(&hc_ptr,
1128 &hdr->daddr);
1129 }
839 } else { 1130 } else {
840 if (addr_type & IPV6_ADDR_LINKLOCAL) { 1131 if (dci) {
841 /* TODO: context lookup */ 1132 iphc1 |= lowpan_compress_ctx_addr(&hc_ptr, &hdr->daddr,
842 iphc1 |= lowpan_compress_addr_64(&hc_ptr, &hdr->daddr, 1133 &dci_entry, daddr,
843 daddr, false); 1134 false);
844 pr_debug("dest address unicast link-local %pI6c " 1135 iphc1 |= LOWPAN_IPHC_DAC;
845 "iphc1 0x%02x\n", &hdr->daddr, iphc1);
846 } else { 1136 } else {
847 pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 1137 if (ipv6_daddr_type & IPV6_ADDR_LINKLOCAL) {
848 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 1138 iphc1 |= lowpan_compress_addr_64(&hc_ptr,
1139 &hdr->daddr,
1140 daddr, false);
1141 pr_debug("dest address unicast link-local %pI6c iphc1 0x%02x\n",
1142 &hdr->daddr, iphc1);
1143 } else {
1144 pr_debug("dest address unicast %pI6c\n",
1145 &hdr->daddr);
1146 lowpan_push_hc_data(&hc_ptr,
1147 hdr->daddr.s6_addr, 16);
1148 }
849 } 1149 }
850 } 1150 }
851 1151