aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154/6lowpan.c
diff options
context:
space:
mode:
authoralex.bluesman.smirnov@gmail.com <alex.bluesman.smirnov@gmail.com>2011-11-10 02:40:14 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-14 00:19:43 -0500
commit3bd5b958c2a2dd1a9b4c8d21e75fb47b062fc941 (patch)
tree6cdd68759b81cf7115976f730537da76b528723e /net/ieee802154/6lowpan.c
parent4d039f684314b707fdae3c7262faf4a80c548194 (diff)
6LoWPAN: UDP header compression
This patch adds support for UDP header compression. Derived from Contiki OS. Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154/6lowpan.c')
-rw-r--r--net/ieee802154/6lowpan.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 39ec6e018227..9bf82d72bb9e 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -246,6 +246,50 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
246 return 0; 246 return 0;
247} 247}
248 248
249static void
250lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
251{
252 struct udphdr *uh = udp_hdr(skb);
253
254 pr_debug("(%s): UDP header compression\n", __func__);
255
256 if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
257 LOWPAN_NHC_UDP_4BIT_PORT) &&
258 ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
259 LOWPAN_NHC_UDP_4BIT_PORT)) {
260 pr_debug("(%s): both ports compression to 4 bits\n", __func__);
261 **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
262 **(hc06_ptr + 1) = /* subtraction is faster */
263 (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
264 ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
265 *hc06_ptr += 2;
266 } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
267 LOWPAN_NHC_UDP_8BIT_PORT) {
268 pr_debug("(%s): remove 8 bits of dest\n", __func__);
269 **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
270 memcpy(*hc06_ptr + 1, &uh->source, 2);
271 **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
272 *hc06_ptr += 4;
273 } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
274 LOWPAN_NHC_UDP_8BIT_PORT) {
275 pr_debug("(%s): remove 8 bits of source\n", __func__);
276 **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
277 memcpy(*hc06_ptr + 1, &uh->dest, 2);
278 **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
279 *hc06_ptr += 4;
280 } else {
281 pr_debug("(%s): can't compress header\n", __func__);
282 **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
283 memcpy(*hc06_ptr + 1, &uh->source, 2);
284 memcpy(*hc06_ptr + 3, &uh->dest, 2);
285 *hc06_ptr += 5;
286 }
287
288 /* checksum is always inline */
289 memcpy(*hc06_ptr, &uh->check, 2);
290 *hc06_ptr += 2;
291}
292
249static u8 lowpan_fetch_skb_u8(struct sk_buff *skb) 293static u8 lowpan_fetch_skb_u8(struct sk_buff *skb)
250{ 294{
251 u8 ret; 295 u8 ret;
@@ -365,8 +409,6 @@ static int lowpan_header_create(struct sk_buff *skb,
365 if (hdr->nexthdr == UIP_PROTO_UDP) 409 if (hdr->nexthdr == UIP_PROTO_UDP)
366 iphc0 |= LOWPAN_IPHC_NH_C; 410 iphc0 |= LOWPAN_IPHC_NH_C;
367 411
368/* TODO: next header compression */
369
370 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 412 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
371 *hc06_ptr = hdr->nexthdr; 413 *hc06_ptr = hdr->nexthdr;
372 hc06_ptr += 1; 414 hc06_ptr += 1;
@@ -454,8 +496,9 @@ static int lowpan_header_create(struct sk_buff *skb,
454 } 496 }
455 } 497 }
456 498
457 /* TODO: UDP header compression */ 499 /* UDP header compression */
458 /* TODO: Next Header compression */ 500 if (hdr->nexthdr == UIP_PROTO_UDP)
501 lowpan_compress_udp_header(&hc06_ptr, skb);
459 502
460 head[0] = iphc0; 503 head[0] = iphc0;
461 head[1] = iphc1; 504 head[1] = iphc1;