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.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 /* Jon's code is based on 6lowpan implementation for Contiki which is:
24 * Copyright (c) 2008, Swedish Institute of Computer Science.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. Neither the name of the Institute nor the names of its contributors
36 * may be used to endorse or promote products derived from this software
37 * without specific prior written permission.
39 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 #include <linux/bitops.h>
53 #include <linux/if_arp.h>
54 #include <linux/module.h>
55 #include <linux/netdevice.h>
56 #include <net/6lowpan.h>
58 #include <net/af_ieee802154.h>
60 /* Uncompress address function for source and
61 * destination address(non-multicast).
63 * address_mode is sam value or dam value.
65 static int uncompress_addr(struct sk_buff
*skb
,
66 struct in6_addr
*ipaddr
, const u8 address_mode
,
67 const u8
*lladdr
, const u8 addr_type
,
72 switch (address_mode
) {
73 case LOWPAN_IPHC_ADDR_00
:
74 /* for global link addresses */
75 fail
= lowpan_fetch_skb(skb
, ipaddr
->s6_addr
, 16);
77 case LOWPAN_IPHC_ADDR_01
:
78 /* fe:80::XXXX:XXXX:XXXX:XXXX */
79 ipaddr
->s6_addr
[0] = 0xFE;
80 ipaddr
->s6_addr
[1] = 0x80;
81 fail
= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[8], 8);
83 case LOWPAN_IPHC_ADDR_02
:
84 /* fe:80::ff:fe00:XXXX */
85 ipaddr
->s6_addr
[0] = 0xFE;
86 ipaddr
->s6_addr
[1] = 0x80;
87 ipaddr
->s6_addr
[11] = 0xFF;
88 ipaddr
->s6_addr
[12] = 0xFE;
89 fail
= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[14], 2);
91 case LOWPAN_IPHC_ADDR_03
:
94 case IEEE802154_ADDR_LONG
:
95 /* fe:80::XXXX:XXXX:XXXX:XXXX
99 ipaddr
->s6_addr
[0] = 0xFE;
100 ipaddr
->s6_addr
[1] = 0x80;
101 memcpy(&ipaddr
->s6_addr
[8], lladdr
, addr_len
);
102 /* second bit-flip (Universe/Local)
103 * is done according RFC2464
105 ipaddr
->s6_addr
[8] ^= 0x02;
107 case IEEE802154_ADDR_SHORT
:
108 /* fe:80::ff:fe00:XXXX
112 * Universe/Local bit is zero.
114 ipaddr
->s6_addr
[0] = 0xFE;
115 ipaddr
->s6_addr
[1] = 0x80;
116 ipaddr
->s6_addr
[11] = 0xFF;
117 ipaddr
->s6_addr
[12] = 0xFE;
118 ipaddr
->s6_addr16
[7] = htons(*((u16
*)lladdr
));
121 pr_debug("Invalid addr_type set\n");
126 pr_debug("Invalid address mode value: 0x%x\n", address_mode
);
131 pr_debug("Failed to fetch skb data\n");
135 raw_dump_inline(NULL
, "Reconstructed ipv6 addr is",
136 ipaddr
->s6_addr
, 16);
141 /* Uncompress address function for source context
142 * based address(non-multicast).
144 static int uncompress_context_based_src_addr(struct sk_buff
*skb
,
145 struct in6_addr
*ipaddr
,
149 case LOWPAN_IPHC_ADDR_00
:
151 * Do nothing, address is already ::
154 case LOWPAN_IPHC_ADDR_01
:
156 case LOWPAN_IPHC_ADDR_02
:
158 case LOWPAN_IPHC_ADDR_03
:
160 netdev_warn(skb
->dev
, "SAM value 0x%x not supported\n", sam
);
163 pr_debug("Invalid sam value: 0x%x\n", sam
);
167 raw_dump_inline(NULL
,
168 "Reconstructed context based ipv6 src addr is",
169 ipaddr
->s6_addr
, 16);
174 /* Uncompress function for multicast destination address,
177 static int lowpan_uncompress_multicast_daddr(struct sk_buff
*skb
,
178 struct in6_addr
*ipaddr
,
184 case LOWPAN_IPHC_DAM_00
:
185 /* 00: 128 bits. The full address
186 * is carried in-line.
188 fail
= lowpan_fetch_skb(skb
, ipaddr
->s6_addr
, 16);
190 case LOWPAN_IPHC_DAM_01
:
191 /* 01: 48 bits. The address takes
192 * the form ffXX::00XX:XXXX:XXXX.
194 ipaddr
->s6_addr
[0] = 0xFF;
195 fail
= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[1], 1);
196 fail
|= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[11], 5);
198 case LOWPAN_IPHC_DAM_10
:
199 /* 10: 32 bits. The address takes
200 * the form ffXX::00XX:XXXX.
202 ipaddr
->s6_addr
[0] = 0xFF;
203 fail
= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[1], 1);
204 fail
|= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[13], 3);
206 case LOWPAN_IPHC_DAM_11
:
207 /* 11: 8 bits. The address takes
208 * the form ff02::00XX.
210 ipaddr
->s6_addr
[0] = 0xFF;
211 ipaddr
->s6_addr
[1] = 0x02;
212 fail
= lowpan_fetch_skb(skb
, &ipaddr
->s6_addr
[15], 1);
215 pr_debug("DAM value has a wrong value: 0x%x\n", dam
);
220 pr_debug("Failed to fetch skb data\n");
224 raw_dump_inline(NULL
, "Reconstructed ipv6 multicast addr is",
225 ipaddr
->s6_addr
, 16);
230 static int uncompress_udp_header(struct sk_buff
*skb
, struct udphdr
*uh
)
235 fail
= lowpan_fetch_skb(skb
, &tmp
, sizeof(tmp
));
237 if ((tmp
& LOWPAN_NHC_UDP_MASK
) == LOWPAN_NHC_UDP_ID
) {
238 pr_debug("UDP header uncompression\n");
239 switch (tmp
& LOWPAN_NHC_UDP_CS_P_11
) {
240 case LOWPAN_NHC_UDP_CS_P_00
:
241 fail
|= lowpan_fetch_skb(skb
, &uh
->source
,
243 fail
|= lowpan_fetch_skb(skb
, &uh
->dest
,
246 case LOWPAN_NHC_UDP_CS_P_01
:
247 fail
|= lowpan_fetch_skb(skb
, &uh
->source
,
249 fail
|= lowpan_fetch_skb(skb
, &val
, sizeof(val
));
250 uh
->dest
= htons(val
+ LOWPAN_NHC_UDP_8BIT_PORT
);
252 case LOWPAN_NHC_UDP_CS_P_10
:
253 fail
|= lowpan_fetch_skb(skb
, &val
, sizeof(val
));
254 uh
->source
= htons(val
+ LOWPAN_NHC_UDP_8BIT_PORT
);
255 fail
|= lowpan_fetch_skb(skb
, &uh
->dest
,
258 case LOWPAN_NHC_UDP_CS_P_11
:
259 fail
|= lowpan_fetch_skb(skb
, &val
, sizeof(val
));
260 uh
->source
= htons(LOWPAN_NHC_UDP_4BIT_PORT
+
262 uh
->dest
= htons(LOWPAN_NHC_UDP_4BIT_PORT
+
266 pr_debug("ERROR: unknown UDP format\n");
270 pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
271 ntohs(uh
->source
), ntohs(uh
->dest
));
274 if (tmp
& LOWPAN_NHC_UDP_CS_C
) {
275 pr_debug_ratelimited("checksum elided currently not supported\n");
278 fail
|= lowpan_fetch_skb(skb
, &uh
->check
,
282 /* UDP length needs to be infered from the lower layers
283 * here, we obtain the hint from the remaining size of the
286 uh
->len
= htons(skb
->len
+ sizeof(struct udphdr
));
287 pr_debug("uncompressed UDP length: src = %d", ntohs(uh
->len
));
289 pr_debug("ERROR: unsupported NH format\n");
301 /* TTL uncompression values */
302 static const u8 lowpan_ttl_values
[] = { 0, 1, 64, 255 };
305 lowpan_header_decompress(struct sk_buff
*skb
, struct net_device
*dev
,
306 const u8
*saddr
, const u8 saddr_type
,
307 const u8 saddr_len
, const u8
*daddr
,
308 const u8 daddr_type
, const u8 daddr_len
,
311 struct ipv6hdr hdr
= {};
312 u8 tmp
, num_context
= 0;
315 raw_dump_table(__func__
, "raw skb data dump uncompressed",
316 skb
->data
, skb
->len
);
318 /* another if the CID flag is set */
319 if (iphc1
& LOWPAN_IPHC_CID
) {
320 pr_debug("CID flag is set, increase header with one\n");
321 if (lowpan_fetch_skb(skb
, &num_context
, sizeof(num_context
)))
327 /* Traffic Class and Flow Label */
328 switch ((iphc0
& LOWPAN_IPHC_TF
) >> 3) {
329 /* Traffic Class and FLow Label carried in-line
330 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
333 if (lowpan_fetch_skb(skb
, &tmp
, sizeof(tmp
)))
336 memcpy(&hdr
.flow_lbl
, &skb
->data
[0], 3);
338 hdr
.priority
= ((tmp
>> 2) & 0x0f);
339 hdr
.flow_lbl
[0] = ((tmp
>> 2) & 0x30) | (tmp
<< 6) |
340 (hdr
.flow_lbl
[0] & 0x0f);
342 /* Traffic class carried in-line
343 * ECN + DSCP (1 byte), Flow Label is elided
346 if (lowpan_fetch_skb(skb
, &tmp
, sizeof(tmp
)))
349 hdr
.priority
= ((tmp
>> 2) & 0x0f);
350 hdr
.flow_lbl
[0] = ((tmp
<< 6) & 0xC0) | ((tmp
>> 2) & 0x30);
352 /* Flow Label carried in-line
353 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
356 if (lowpan_fetch_skb(skb
, &tmp
, sizeof(tmp
)))
359 hdr
.flow_lbl
[0] = (skb
->data
[0] & 0x0F) | ((tmp
>> 2) & 0x30);
360 memcpy(&hdr
.flow_lbl
[1], &skb
->data
[0], 2);
363 /* Traffic Class and Flow Label are elided */
371 if ((iphc0
& LOWPAN_IPHC_NH_C
) == 0) {
372 /* Next header is carried inline */
373 if (lowpan_fetch_skb(skb
, &hdr
.nexthdr
, sizeof(hdr
.nexthdr
)))
376 pr_debug("NH flag is set, next header carried inline: %02x\n",
381 if ((iphc0
& 0x03) != LOWPAN_IPHC_TTL_I
) {
382 hdr
.hop_limit
= lowpan_ttl_values
[iphc0
& 0x03];
384 if (lowpan_fetch_skb(skb
, &hdr
.hop_limit
,
385 sizeof(hdr
.hop_limit
)))
389 /* Extract SAM to the tmp variable */
390 tmp
= ((iphc1
& LOWPAN_IPHC_SAM
) >> LOWPAN_IPHC_SAM_BIT
) & 0x03;
392 if (iphc1
& LOWPAN_IPHC_SAC
) {
393 /* Source address context based uncompression */
394 pr_debug("SAC bit is set. Handle context based source address.\n");
395 err
= uncompress_context_based_src_addr(skb
, &hdr
.saddr
, tmp
);
397 /* Source address uncompression */
398 pr_debug("source address stateless compression\n");
399 err
= uncompress_addr(skb
, &hdr
.saddr
, tmp
, saddr
,
400 saddr_type
, saddr_len
);
403 /* Check on error of previous branch */
407 /* Extract DAM to the tmp variable */
408 tmp
= ((iphc1
& LOWPAN_IPHC_DAM_11
) >> LOWPAN_IPHC_DAM_BIT
) & 0x03;
410 /* check for Multicast Compression */
411 if (iphc1
& LOWPAN_IPHC_M
) {
412 if (iphc1
& LOWPAN_IPHC_DAC
) {
413 pr_debug("dest: context-based mcast compression\n");
414 /* TODO: implement this */
416 err
= lowpan_uncompress_multicast_daddr(skb
, &hdr
.daddr
,
423 err
= uncompress_addr(skb
, &hdr
.daddr
, tmp
, daddr
,
424 daddr_type
, daddr_len
);
425 pr_debug("dest: stateless compression mode %d dest %pI6c\n",
431 /* UDP data uncompression */
432 if (iphc0
& LOWPAN_IPHC_NH_C
) {
434 const int needed
= sizeof(struct udphdr
) + sizeof(hdr
);
436 if (uncompress_udp_header(skb
, &uh
))
439 /* replace the compressed UDP head by the uncompressed UDP
442 err
= skb_cow(skb
, needed
);
446 skb_push(skb
, sizeof(struct udphdr
));
447 skb_reset_transport_header(skb
);
448 skb_copy_to_linear_data(skb
, &uh
, sizeof(struct udphdr
));
450 raw_dump_table(__func__
, "raw UDP header dump",
451 (u8
*)&uh
, sizeof(uh
));
453 hdr
.nexthdr
= UIP_PROTO_UDP
;
455 err
= skb_cow(skb
, sizeof(hdr
));
460 hdr
.payload_len
= htons(skb
->len
);
462 pr_debug("skb headroom size = %d, data length = %d\n",
463 skb_headroom(skb
), skb
->len
);
465 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
466 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
467 hdr
.version
, ntohs(hdr
.payload_len
), hdr
.nexthdr
,
468 hdr
.hop_limit
, &hdr
.daddr
);
470 skb_push(skb
, sizeof(hdr
));
471 skb_reset_network_header(skb
);
472 skb_copy_to_linear_data(skb
, &hdr
, sizeof(hdr
));
474 raw_dump_table(__func__
, "raw header dump", (u8
*)&hdr
, sizeof(hdr
));
478 EXPORT_SYMBOL_GPL(lowpan_header_decompress
);
480 static u8
lowpan_compress_addr_64(u8
**hc_ptr
, u8 shift
,
481 const struct in6_addr
*ipaddr
,
482 const unsigned char *lladdr
)
486 if (is_addr_mac_addr_based(ipaddr
, lladdr
)) {
487 val
= 3; /* 0-bits */
488 pr_debug("address compression 0 bits\n");
489 } else if (lowpan_is_iid_16_bit_compressable(ipaddr
)) {
490 /* compress IID to 16 bits xxxx::XXXX */
491 lowpan_push_hc_data(hc_ptr
, &ipaddr
->s6_addr16
[7], 2);
492 val
= 2; /* 16-bits */
493 raw_dump_inline(NULL
, "Compressed ipv6 addr is (16 bits)",
496 /* do not compress IID => xxxx::IID */
497 lowpan_push_hc_data(hc_ptr
, &ipaddr
->s6_addr16
[4], 8);
498 val
= 1; /* 64-bits */
499 raw_dump_inline(NULL
, "Compressed ipv6 addr is (64 bits)",
503 return rol8(val
, shift
);
506 static void compress_udp_header(u8
**hc_ptr
, struct sk_buff
*skb
)
511 /* In the case of RAW sockets the transport header is not set by
512 * the ip6 stack so we must set it ourselves
514 if (skb
->transport_header
== skb
->network_header
)
515 skb_set_transport_header(skb
, sizeof(struct ipv6hdr
));
519 if (((ntohs(uh
->source
) & LOWPAN_NHC_UDP_4BIT_MASK
) ==
520 LOWPAN_NHC_UDP_4BIT_PORT
) &&
521 ((ntohs(uh
->dest
) & LOWPAN_NHC_UDP_4BIT_MASK
) ==
522 LOWPAN_NHC_UDP_4BIT_PORT
)) {
523 pr_debug("UDP header: both ports compression to 4 bits\n");
524 /* compression value */
525 tmp
= LOWPAN_NHC_UDP_CS_P_11
;
526 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
527 /* source and destination port */
528 tmp
= ntohs(uh
->dest
) - LOWPAN_NHC_UDP_4BIT_PORT
+
529 ((ntohs(uh
->source
) - LOWPAN_NHC_UDP_4BIT_PORT
) << 4);
530 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
531 } else if ((ntohs(uh
->dest
) & LOWPAN_NHC_UDP_8BIT_MASK
) ==
532 LOWPAN_NHC_UDP_8BIT_PORT
) {
533 pr_debug("UDP header: remove 8 bits of dest\n");
534 /* compression value */
535 tmp
= LOWPAN_NHC_UDP_CS_P_01
;
536 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
538 lowpan_push_hc_data(hc_ptr
, &uh
->source
, sizeof(uh
->source
));
539 /* destination port */
540 tmp
= ntohs(uh
->dest
) - LOWPAN_NHC_UDP_8BIT_PORT
;
541 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
542 } else if ((ntohs(uh
->source
) & LOWPAN_NHC_UDP_8BIT_MASK
) ==
543 LOWPAN_NHC_UDP_8BIT_PORT
) {
544 pr_debug("UDP header: remove 8 bits of source\n");
545 /* compression value */
546 tmp
= LOWPAN_NHC_UDP_CS_P_10
;
547 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
549 tmp
= ntohs(uh
->source
) - LOWPAN_NHC_UDP_8BIT_PORT
;
550 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
551 /* destination port */
552 lowpan_push_hc_data(hc_ptr
, &uh
->dest
, sizeof(uh
->dest
));
554 pr_debug("UDP header: can't compress\n");
555 /* compression value */
556 tmp
= LOWPAN_NHC_UDP_CS_P_00
;
557 lowpan_push_hc_data(hc_ptr
, &tmp
, sizeof(tmp
));
559 lowpan_push_hc_data(hc_ptr
, &uh
->source
, sizeof(uh
->source
));
560 /* destination port */
561 lowpan_push_hc_data(hc_ptr
, &uh
->dest
, sizeof(uh
->dest
));
564 /* checksum is always inline */
565 lowpan_push_hc_data(hc_ptr
, &uh
->check
, sizeof(uh
->check
));
567 /* skip the UDP header */
568 skb_pull(skb
, sizeof(struct udphdr
));
571 int lowpan_header_compress(struct sk_buff
*skb
, struct net_device
*dev
,
572 unsigned short type
, const void *_daddr
,
573 const void *_saddr
, unsigned int len
)
575 u8 tmp
, iphc0
, iphc1
, *hc_ptr
;
580 if (type
!= ETH_P_IPV6
)
586 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
587 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
588 hdr
->version
, ntohs(hdr
->payload_len
), hdr
->nexthdr
,
589 hdr
->hop_limit
, &hdr
->daddr
);
591 raw_dump_table(__func__
, "raw skb network header dump",
592 skb_network_header(skb
), sizeof(struct ipv6hdr
));
594 /* As we copy some bit-length fields, in the IPHC encoding bytes,
595 * we sometimes use |=
596 * If the field is 0, and the current bit value in memory is 1,
597 * this does not work. We therefore reset the IPHC encoding here
599 iphc0
= LOWPAN_DISPATCH_IPHC
;
602 /* TODO: context lookup */
604 raw_dump_inline(__func__
, "saddr",
605 (unsigned char *)_saddr
, IEEE802154_ADDR_LEN
);
606 raw_dump_inline(__func__
, "daddr",
607 (unsigned char *)_daddr
, IEEE802154_ADDR_LEN
);
609 raw_dump_table(__func__
, "sending raw skb network uncompressed packet",
610 skb
->data
, skb
->len
);
612 /* Traffic class, flow label
613 * If flow label is 0, compress it. If traffic class is 0, compress it
614 * We have to process both in the same time as the offset of traffic
615 * class depends on the presence of version and flow label
618 /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
619 tmp
= (hdr
->priority
<< 4) | (hdr
->flow_lbl
[0] >> 4);
620 tmp
= ((tmp
& 0x03) << 6) | (tmp
>> 2);
622 if (((hdr
->flow_lbl
[0] & 0x0F) == 0) &&
623 (hdr
->flow_lbl
[1] == 0) && (hdr
->flow_lbl
[2] == 0)) {
624 /* flow label can be compressed */
625 iphc0
|= LOWPAN_IPHC_FL_C
;
626 if ((hdr
->priority
== 0) &&
627 ((hdr
->flow_lbl
[0] & 0xF0) == 0)) {
628 /* compress (elide) all */
629 iphc0
|= LOWPAN_IPHC_TC_C
;
631 /* compress only the flow label */
636 /* Flow label cannot be compressed */
637 if ((hdr
->priority
== 0) &&
638 ((hdr
->flow_lbl
[0] & 0xF0) == 0)) {
639 /* compress only traffic class */
640 iphc0
|= LOWPAN_IPHC_TC_C
;
641 *hc_ptr
= (tmp
& 0xc0) | (hdr
->flow_lbl
[0] & 0x0F);
642 memcpy(hc_ptr
+ 1, &hdr
->flow_lbl
[1], 2);
645 /* compress nothing */
646 memcpy(hc_ptr
, hdr
, 4);
647 /* replace the top byte with new ECN | DSCP format */
653 /* NOTE: payload length is always compressed */
655 /* Next Header is compress if UDP */
656 if (hdr
->nexthdr
== UIP_PROTO_UDP
)
657 iphc0
|= LOWPAN_IPHC_NH_C
;
659 if ((iphc0
& LOWPAN_IPHC_NH_C
) == 0)
660 lowpan_push_hc_data(&hc_ptr
, &hdr
->nexthdr
,
661 sizeof(hdr
->nexthdr
));
664 * if 1: compress, encoding is 01
665 * if 64: compress, encoding is 10
666 * if 255: compress, encoding is 11
667 * else do not compress
669 switch (hdr
->hop_limit
) {
671 iphc0
|= LOWPAN_IPHC_TTL_1
;
674 iphc0
|= LOWPAN_IPHC_TTL_64
;
677 iphc0
|= LOWPAN_IPHC_TTL_255
;
680 lowpan_push_hc_data(&hc_ptr
, &hdr
->hop_limit
,
681 sizeof(hdr
->hop_limit
));
684 addr_type
= ipv6_addr_type(&hdr
->saddr
);
685 /* source address compression */
686 if (addr_type
== IPV6_ADDR_ANY
) {
687 pr_debug("source address is unspecified, setting SAC\n");
688 iphc1
|= LOWPAN_IPHC_SAC
;
690 if (addr_type
& IPV6_ADDR_LINKLOCAL
) {
691 iphc1
|= lowpan_compress_addr_64(&hc_ptr
,
693 &hdr
->saddr
, _saddr
);
694 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
697 pr_debug("send the full source address\n");
698 lowpan_push_hc_data(&hc_ptr
, hdr
->saddr
.s6_addr
, 16);
702 addr_type
= ipv6_addr_type(&hdr
->daddr
);
703 /* destination address compression */
704 if (addr_type
& IPV6_ADDR_MULTICAST
) {
705 pr_debug("destination address is multicast: ");
706 iphc1
|= LOWPAN_IPHC_M
;
707 if (lowpan_is_mcast_addr_compressable8(&hdr
->daddr
)) {
708 pr_debug("compressed to 1 octet\n");
709 iphc1
|= LOWPAN_IPHC_DAM_11
;
711 lowpan_push_hc_data(&hc_ptr
,
712 &hdr
->daddr
.s6_addr
[15], 1);
713 } else if (lowpan_is_mcast_addr_compressable32(&hdr
->daddr
)) {
714 pr_debug("compressed to 4 octets\n");
715 iphc1
|= LOWPAN_IPHC_DAM_10
;
716 /* second byte + the last three */
717 lowpan_push_hc_data(&hc_ptr
,
718 &hdr
->daddr
.s6_addr
[1], 1);
719 lowpan_push_hc_data(&hc_ptr
,
720 &hdr
->daddr
.s6_addr
[13], 3);
721 } else if (lowpan_is_mcast_addr_compressable48(&hdr
->daddr
)) {
722 pr_debug("compressed to 6 octets\n");
723 iphc1
|= LOWPAN_IPHC_DAM_01
;
724 /* second byte + the last five */
725 lowpan_push_hc_data(&hc_ptr
,
726 &hdr
->daddr
.s6_addr
[1], 1);
727 lowpan_push_hc_data(&hc_ptr
,
728 &hdr
->daddr
.s6_addr
[11], 5);
730 pr_debug("using full address\n");
731 iphc1
|= LOWPAN_IPHC_DAM_00
;
732 lowpan_push_hc_data(&hc_ptr
, hdr
->daddr
.s6_addr
, 16);
735 if (addr_type
& IPV6_ADDR_LINKLOCAL
) {
736 /* TODO: context lookup */
737 iphc1
|= lowpan_compress_addr_64(&hc_ptr
,
738 LOWPAN_IPHC_DAM_BIT
, &hdr
->daddr
, _daddr
);
739 pr_debug("dest address unicast link-local %pI6c "
740 "iphc1 0x%02x\n", &hdr
->daddr
, iphc1
);
742 pr_debug("dest address unicast %pI6c\n", &hdr
->daddr
);
743 lowpan_push_hc_data(&hc_ptr
, hdr
->daddr
.s6_addr
, 16);
747 /* UDP header compression */
748 if (hdr
->nexthdr
== UIP_PROTO_UDP
)
749 compress_udp_header(&hc_ptr
, skb
);
754 skb_pull(skb
, sizeof(struct ipv6hdr
));
755 skb_reset_transport_header(skb
);
756 memcpy(skb_push(skb
, hc_ptr
- head
), head
, hc_ptr
- head
);
757 skb_reset_network_header(skb
);
759 pr_debug("header len %d skb %u\n", (int)(hc_ptr
- head
), skb
->len
);
761 raw_dump_table(__func__
, "raw skb data dump compressed",
762 skb
->data
, skb
->len
);
765 EXPORT_SYMBOL_GPL(lowpan_header_compress
);
767 MODULE_LICENSE("GPL");
This page took 0.049111 seconds and 5 git commands to generate.