2 * Copyright 2011, Siemens AG
3 * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
6 /* Based on patches from Jon Smirl <jonsmirl@gmail.com>
7 * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 /* Jon's code is based on 6lowpan implementation for Contiki which is:
21 * Copyright (c) 2008, Swedish Institute of Computer Science.
22 * All rights reserved.
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 * 3. Neither the name of the Institute nor the names of its contributors
33 * may be used to endorse or promote products derived from this software
34 * without specific prior written permission.
36 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 #include <linux/bitops.h>
50 #include <linux/if_arp.h>
51 #include <linux/module.h>
52 #include <linux/netdevice.h>
53 #include <net/6lowpan.h>
55 #include <net/af_ieee802154.h>
57 /* Uncompress address function for source and
58 * destination address(non-multicast).
60 * address_mode is sam value or dam value.
62 static int uncompress_addr(struct sk_buff *skb,
63 struct in6_addr *ipaddr, const u8 address_mode,
64 const u8 *lladdr, const u8 addr_type,
69 switch (address_mode) {
70 case LOWPAN_IPHC_ADDR_00:
71 /* for global link addresses */
72 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
74 case LOWPAN_IPHC_ADDR_01:
75 /* fe:80::XXXX:XXXX:XXXX:XXXX */
76 ipaddr->s6_addr[0] = 0xFE;
77 ipaddr->s6_addr[1] = 0x80;
78 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
80 case LOWPAN_IPHC_ADDR_02:
81 /* fe:80::ff:fe00:XXXX */
82 ipaddr->s6_addr[0] = 0xFE;
83 ipaddr->s6_addr[1] = 0x80;
84 ipaddr->s6_addr[11] = 0xFF;
85 ipaddr->s6_addr[12] = 0xFE;
86 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
88 case LOWPAN_IPHC_ADDR_03:
91 case IEEE802154_ADDR_LONG:
92 /* fe:80::XXXX:XXXX:XXXX:XXXX
96 ipaddr->s6_addr[0] = 0xFE;
97 ipaddr->s6_addr[1] = 0x80;
98 memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
99 /* second bit-flip (Universe/Local)
100 * is done according RFC2464
102 ipaddr->s6_addr[8] ^= 0x02;
104 case IEEE802154_ADDR_SHORT:
105 /* fe:80::ff:fe00:XXXX
109 * Universe/Local bit is zero.
111 ipaddr->s6_addr[0] = 0xFE;
112 ipaddr->s6_addr[1] = 0x80;
113 ipaddr->s6_addr[11] = 0xFF;
114 ipaddr->s6_addr[12] = 0xFE;
115 ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
118 pr_debug("Invalid addr_type set\n");
123 pr_debug("Invalid address mode value: 0x%x\n", address_mode);
128 pr_debug("Failed to fetch skb data\n");
132 raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
133 ipaddr->s6_addr, 16);
138 /* Uncompress address function for source context
139 * based address(non-multicast).
141 static int uncompress_context_based_src_addr(struct sk_buff *skb,
142 struct in6_addr *ipaddr,
146 case LOWPAN_IPHC_ADDR_00:
148 * Do nothing, address is already ::
151 case LOWPAN_IPHC_ADDR_01:
153 case LOWPAN_IPHC_ADDR_02:
155 case LOWPAN_IPHC_ADDR_03:
157 netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
160 pr_debug("Invalid sam value: 0x%x\n", sam);
164 raw_dump_inline(NULL,
165 "Reconstructed context based ipv6 src addr is",
166 ipaddr->s6_addr, 16);
171 /* Uncompress function for multicast destination address,
174 static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
175 struct in6_addr *ipaddr,
181 case LOWPAN_IPHC_DAM_00:
182 /* 00: 128 bits. The full address
183 * is carried in-line.
185 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
187 case LOWPAN_IPHC_DAM_01:
188 /* 01: 48 bits. The address takes
189 * the form ffXX::00XX:XXXX:XXXX.
191 ipaddr->s6_addr[0] = 0xFF;
192 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
193 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
195 case LOWPAN_IPHC_DAM_10:
196 /* 10: 32 bits. The address takes
197 * the form ffXX::00XX:XXXX.
199 ipaddr->s6_addr[0] = 0xFF;
200 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
201 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
203 case LOWPAN_IPHC_DAM_11:
204 /* 11: 8 bits. The address takes
205 * the form ff02::00XX.
207 ipaddr->s6_addr[0] = 0xFF;
208 ipaddr->s6_addr[1] = 0x02;
209 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
212 pr_debug("DAM value has a wrong value: 0x%x\n", dam);
217 pr_debug("Failed to fetch skb data\n");
221 raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
222 ipaddr->s6_addr, 16);
227 static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
232 fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp));
234 if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
235 pr_debug("UDP header uncompression\n");
236 switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
237 case LOWPAN_NHC_UDP_CS_P_00:
238 fail |= lowpan_fetch_skb(skb, &uh->source,
240 fail |= lowpan_fetch_skb(skb, &uh->dest,
243 case LOWPAN_NHC_UDP_CS_P_01:
244 fail |= lowpan_fetch_skb(skb, &uh->source,
246 fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
247 uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
249 case LOWPAN_NHC_UDP_CS_P_10:
250 fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
251 uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
252 fail |= lowpan_fetch_skb(skb, &uh->dest,
255 case LOWPAN_NHC_UDP_CS_P_11:
256 fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
257 uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
259 uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
263 pr_debug("ERROR: unknown UDP format\n");
267 pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
268 ntohs(uh->source), ntohs(uh->dest));
271 if (tmp & LOWPAN_NHC_UDP_CS_C) {
272 pr_debug_ratelimited("checksum elided currently not supported\n");
275 fail |= lowpan_fetch_skb(skb, &uh->check,
279 /* UDP length needs to be infered from the lower layers
280 * here, we obtain the hint from the remaining size of the
283 uh->len = htons(skb->len + sizeof(struct udphdr));
284 pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len));
286 pr_debug("ERROR: unsupported NH format\n");
298 /* TTL uncompression values */
299 static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
302 lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
303 const u8 *saddr, const u8 saddr_type,
304 const u8 saddr_len, const u8 *daddr,
305 const u8 daddr_type, const u8 daddr_len,
308 struct ipv6hdr hdr = {};
309 u8 tmp, num_context = 0;
312 raw_dump_table(__func__, "raw skb data dump uncompressed",
313 skb->data, skb->len);
315 /* another if the CID flag is set */
316 if (iphc1 & LOWPAN_IPHC_CID) {
317 pr_debug("CID flag is set, increase header with one\n");
318 if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
324 /* Traffic Class and Flow Label */
325 switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
326 /* Traffic Class and FLow Label carried in-line
327 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
330 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
333 memcpy(&hdr.flow_lbl, &skb->data[0], 3);
335 hdr.priority = ((tmp >> 2) & 0x0f);
336 hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
337 (hdr.flow_lbl[0] & 0x0f);
339 /* Traffic class carried in-line
340 * ECN + DSCP (1 byte), Flow Label is elided
343 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
346 hdr.priority = ((tmp >> 2) & 0x0f);
347 hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
349 /* Flow Label carried in-line
350 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
353 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
356 hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
357 memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
360 /* Traffic Class and Flow Label are elided */
368 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
369 /* Next header is carried inline */
370 if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
373 pr_debug("NH flag is set, next header carried inline: %02x\n",
378 if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
379 hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
381 if (lowpan_fetch_skb(skb, &hdr.hop_limit,
382 sizeof(hdr.hop_limit)))
386 /* Extract SAM to the tmp variable */
387 tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
389 if (iphc1 & LOWPAN_IPHC_SAC) {
390 /* Source address context based uncompression */
391 pr_debug("SAC bit is set. Handle context based source address.\n");
392 err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp);
394 /* Source address uncompression */
395 pr_debug("source address stateless compression\n");
396 err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
397 saddr_type, saddr_len);
400 /* Check on error of previous branch */
404 /* Extract DAM to the tmp variable */
405 tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
407 /* check for Multicast Compression */
408 if (iphc1 & LOWPAN_IPHC_M) {
409 if (iphc1 & LOWPAN_IPHC_DAC) {
410 pr_debug("dest: context-based mcast compression\n");
411 /* TODO: implement this */
413 err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
420 err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
421 daddr_type, daddr_len);
422 pr_debug("dest: stateless compression mode %d dest %pI6c\n",
428 /* UDP data uncompression */
429 if (iphc0 & LOWPAN_IPHC_NH_C) {
431 const int needed = sizeof(struct udphdr) + sizeof(hdr);
433 if (uncompress_udp_header(skb, &uh))
436 /* replace the compressed UDP head by the uncompressed UDP
439 err = skb_cow(skb, needed);
443 skb_push(skb, sizeof(struct udphdr));
444 skb_reset_transport_header(skb);
445 skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
447 raw_dump_table(__func__, "raw UDP header dump",
448 (u8 *)&uh, sizeof(uh));
450 hdr.nexthdr = UIP_PROTO_UDP;
452 err = skb_cow(skb, sizeof(hdr));
457 hdr.payload_len = htons(skb->len);
459 pr_debug("skb headroom size = %d, data length = %d\n",
460 skb_headroom(skb), skb->len);
462 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
463 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
464 hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
465 hdr.hop_limit, &hdr.daddr);
467 skb_push(skb, sizeof(hdr));
468 skb_reset_network_header(skb);
469 skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
471 raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
475 EXPORT_SYMBOL_GPL(lowpan_header_decompress);
477 static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
478 const struct in6_addr *ipaddr,
479 const unsigned char *lladdr)
483 if (is_addr_mac_addr_based(ipaddr, lladdr)) {
484 val = 3; /* 0-bits */
485 pr_debug("address compression 0 bits\n");
486 } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
487 /* compress IID to 16 bits xxxx::XXXX */
488 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
489 val = 2; /* 16-bits */
490 raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
493 /* do not compress IID => xxxx::IID */
494 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
495 val = 1; /* 64-bits */
496 raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
500 return rol8(val, shift);
503 static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb)
508 /* In the case of RAW sockets the transport header is not set by
509 * the ip6 stack so we must set it ourselves
511 if (skb->transport_header == skb->network_header)
512 skb_set_transport_header(skb, sizeof(struct ipv6hdr));
516 if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
517 LOWPAN_NHC_UDP_4BIT_PORT) &&
518 ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
519 LOWPAN_NHC_UDP_4BIT_PORT)) {
520 pr_debug("UDP header: both ports compression to 4 bits\n");
521 /* compression value */
522 tmp = LOWPAN_NHC_UDP_CS_P_11;
523 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
524 /* source and destination port */
525 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
526 ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
527 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
528 } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
529 LOWPAN_NHC_UDP_8BIT_PORT) {
530 pr_debug("UDP header: remove 8 bits of dest\n");
531 /* compression value */
532 tmp = LOWPAN_NHC_UDP_CS_P_01;
533 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
535 lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
536 /* destination port */
537 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
538 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
539 } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
540 LOWPAN_NHC_UDP_8BIT_PORT) {
541 pr_debug("UDP header: remove 8 bits of source\n");
542 /* compression value */
543 tmp = LOWPAN_NHC_UDP_CS_P_10;
544 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
546 tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
547 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
548 /* destination port */
549 lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
551 pr_debug("UDP header: can't compress\n");
552 /* compression value */
553 tmp = LOWPAN_NHC_UDP_CS_P_00;
554 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
556 lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
557 /* destination port */
558 lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
561 /* checksum is always inline */
562 lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check));
564 /* skip the UDP header */
565 skb_pull(skb, sizeof(struct udphdr));
568 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
569 unsigned short type, const void *_daddr,
570 const void *_saddr, unsigned int len)
572 u8 tmp, iphc0, iphc1, *hc_ptr;
577 if (type != ETH_P_IPV6)
583 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
584 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
585 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
586 hdr->hop_limit, &hdr->daddr);
588 raw_dump_table(__func__, "raw skb network header dump",
589 skb_network_header(skb), sizeof(struct ipv6hdr));
591 /* As we copy some bit-length fields, in the IPHC encoding bytes,
592 * we sometimes use |=
593 * If the field is 0, and the current bit value in memory is 1,
594 * this does not work. We therefore reset the IPHC encoding here
596 iphc0 = LOWPAN_DISPATCH_IPHC;
599 /* TODO: context lookup */
601 raw_dump_inline(__func__, "saddr",
602 (unsigned char *)_saddr, IEEE802154_ADDR_LEN);
603 raw_dump_inline(__func__, "daddr",
604 (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
606 raw_dump_table(__func__, "sending raw skb network uncompressed packet",
607 skb->data, skb->len);
609 /* Traffic class, flow label
610 * If flow label is 0, compress it. If traffic class is 0, compress it
611 * We have to process both in the same time as the offset of traffic
612 * class depends on the presence of version and flow label
615 /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
616 tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
617 tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
619 if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
620 (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
621 /* flow label can be compressed */
622 iphc0 |= LOWPAN_IPHC_FL_C;
623 if ((hdr->priority == 0) &&
624 ((hdr->flow_lbl[0] & 0xF0) == 0)) {
625 /* compress (elide) all */
626 iphc0 |= LOWPAN_IPHC_TC_C;
628 /* compress only the flow label */
633 /* Flow label cannot be compressed */
634 if ((hdr->priority == 0) &&
635 ((hdr->flow_lbl[0] & 0xF0) == 0)) {
636 /* compress only traffic class */
637 iphc0 |= LOWPAN_IPHC_TC_C;
638 *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
639 memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2);
642 /* compress nothing */
643 memcpy(hc_ptr, hdr, 4);
644 /* replace the top byte with new ECN | DSCP format */
650 /* NOTE: payload length is always compressed */
652 /* Next Header is compress if UDP */
653 if (hdr->nexthdr == UIP_PROTO_UDP)
654 iphc0 |= LOWPAN_IPHC_NH_C;
656 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0)
657 lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
658 sizeof(hdr->nexthdr));
661 * if 1: compress, encoding is 01
662 * if 64: compress, encoding is 10
663 * if 255: compress, encoding is 11
664 * else do not compress
666 switch (hdr->hop_limit) {
668 iphc0 |= LOWPAN_IPHC_TTL_1;
671 iphc0 |= LOWPAN_IPHC_TTL_64;
674 iphc0 |= LOWPAN_IPHC_TTL_255;
677 lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
678 sizeof(hdr->hop_limit));
681 addr_type = ipv6_addr_type(&hdr->saddr);
682 /* source address compression */
683 if (addr_type == IPV6_ADDR_ANY) {
684 pr_debug("source address is unspecified, setting SAC\n");
685 iphc1 |= LOWPAN_IPHC_SAC;
687 if (addr_type & IPV6_ADDR_LINKLOCAL) {
688 iphc1 |= lowpan_compress_addr_64(&hc_ptr,
690 &hdr->saddr, _saddr);
691 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
694 pr_debug("send the full source address\n");
695 lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16);
699 addr_type = ipv6_addr_type(&hdr->daddr);
700 /* destination address compression */
701 if (addr_type & IPV6_ADDR_MULTICAST) {
702 pr_debug("destination address is multicast: ");
703 iphc1 |= LOWPAN_IPHC_M;
704 if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
705 pr_debug("compressed to 1 octet\n");
706 iphc1 |= LOWPAN_IPHC_DAM_11;
708 lowpan_push_hc_data(&hc_ptr,
709 &hdr->daddr.s6_addr[15], 1);
710 } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
711 pr_debug("compressed to 4 octets\n");
712 iphc1 |= LOWPAN_IPHC_DAM_10;
713 /* second byte + the last three */
714 lowpan_push_hc_data(&hc_ptr,
715 &hdr->daddr.s6_addr[1], 1);
716 lowpan_push_hc_data(&hc_ptr,
717 &hdr->daddr.s6_addr[13], 3);
718 } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
719 pr_debug("compressed to 6 octets\n");
720 iphc1 |= LOWPAN_IPHC_DAM_01;
721 /* second byte + the last five */
722 lowpan_push_hc_data(&hc_ptr,
723 &hdr->daddr.s6_addr[1], 1);
724 lowpan_push_hc_data(&hc_ptr,
725 &hdr->daddr.s6_addr[11], 5);
727 pr_debug("using full address\n");
728 iphc1 |= LOWPAN_IPHC_DAM_00;
729 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
732 if (addr_type & IPV6_ADDR_LINKLOCAL) {
733 /* TODO: context lookup */
734 iphc1 |= lowpan_compress_addr_64(&hc_ptr,
735 LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
736 pr_debug("dest address unicast link-local %pI6c "
737 "iphc1 0x%02x\n", &hdr->daddr, iphc1);
739 pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
740 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
744 /* UDP header compression */
745 if (hdr->nexthdr == UIP_PROTO_UDP)
746 compress_udp_header(&hc_ptr, skb);
751 skb_pull(skb, sizeof(struct ipv6hdr));
752 skb_reset_transport_header(skb);
753 memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
754 skb_reset_network_header(skb);
756 pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
758 raw_dump_table(__func__, "raw skb data dump compressed",
759 skb->data, skb->len);
762 EXPORT_SYMBOL_GPL(lowpan_header_compress);
764 MODULE_LICENSE("GPL");