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");