diff options
author | David S. Miller <davem@davemloft.net> | 2014-08-05 16:18:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-05 16:18:20 -0400 |
commit | aef4f5b6db654e512ebcccab2a6e50424c05d2f9 (patch) | |
tree | 4daaee5ac85d1128233a45908dac5212f38ec7aa /net/6lowpan | |
parent | 61ab9efddf51cbc0d57356a4d650785cf5721fbe (diff) | |
parent | dc6be9f54a4ecb0a09765d1f515ed947d86b7528 (diff) |
Merge tag 'master-2014-07-31' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
Conflicts:
net/6lowpan/iphc.c
Minor conflicts in iphc.c were changes overlapping with some
style cleanups.
John W. Linville says:
====================
Please pull this last(?) batch of wireless change intended for the
3.17 stream...
For the NFC bits, Samuel says:
"This is a rather quiet one, we have:
- A new driver from ST Microelectronics for their NCI ST21NFCB,
including device tree support.
- p2p support for the ST21NFCA driver
- A few fixes an enhancements for the NFC digital laye"
For the Atheros bits, Kalle says:
"Michal and Janusz did some important RX aggregation fixes, basically we
were missing RX reordering altogether. The 10.1 firmware doesn't support
Ad-Hoc mode and Michal fixed ath10k so that it doesn't advertise Ad-Hoc
support with that firmware. Also he implemented a workaround for a KVM
issue."
For the Bluetooth bits, Gustavo and Johan say:
"To quote Gustavo from his previous request:
'Some last minute fixes for -next. We have a fix for a use after free in
RFCOMM, another fix to an issue with ADV_DIRECT_IND and one for ADV_IND with
auto-connection handling. Last, we added support for reading the codec and
MWS setting for controllers that support these features.'
Additionally there are fixes to LE scanning, an update to conform to the 4.1
core specification as well as fixes for tracking the page scan state. All
of these fixes are important for 3.17."
And,
"We've got:
- 6lowpan fixes/cleanups
- A couple crash fixes, one for the Marvell HCI driver and another in LE SMP.
- Fix for an incorrect connected state check
- Fix for the bondable requirement during pairing (an issue which had
crept in because of using "pairable" when in fact the actual meaning
was "bondable" (these have different meanings in Bluetooth)"
Along with those are some late-breaking hardware support patches in
brcmfmac and b43 as well as a stray ath9k patch.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/6lowpan')
-rw-r--r-- | net/6lowpan/iphc.c | 212 |
1 files changed, 105 insertions, 107 deletions
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index a1b7117a9600..142eef55c9e2 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c | |||
@@ -177,8 +177,8 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, | |||
177 | struct sk_buff *new; | 177 | struct sk_buff *new; |
178 | int stat; | 178 | int stat; |
179 | 179 | ||
180 | new = skb_copy_expand(skb, sizeof(struct ipv6hdr), | 180 | new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), |
181 | skb_tailroom(skb), GFP_ATOMIC); | 181 | GFP_ATOMIC); |
182 | kfree_skb(skb); | 182 | kfree_skb(skb); |
183 | 183 | ||
184 | if (!new) | 184 | if (!new) |
@@ -205,10 +205,9 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, | |||
205 | /* Uncompress function for multicast destination address, | 205 | /* Uncompress function for multicast destination address, |
206 | * when M bit is set. | 206 | * when M bit is set. |
207 | */ | 207 | */ |
208 | static int | 208 | static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb, |
209 | lowpan_uncompress_multicast_daddr(struct sk_buff *skb, | 209 | struct in6_addr *ipaddr, |
210 | struct in6_addr *ipaddr, | 210 | const u8 dam) |
211 | const u8 dam) | ||
212 | { | 211 | { |
213 | bool fail; | 212 | bool fail; |
214 | 213 | ||
@@ -254,41 +253,41 @@ lowpan_uncompress_multicast_daddr(struct sk_buff *skb, | |||
254 | } | 253 | } |
255 | 254 | ||
256 | raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", | 255 | raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", |
257 | ipaddr->s6_addr, 16); | 256 | ipaddr->s6_addr, 16); |
258 | 257 | ||
259 | return 0; | 258 | return 0; |
260 | } | 259 | } |
261 | 260 | ||
262 | static int | 261 | static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) |
263 | uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | ||
264 | { | 262 | { |
265 | bool fail; | 263 | bool fail; |
266 | u8 tmp = 0, val = 0; | 264 | u8 tmp = 0, val = 0; |
267 | 265 | ||
268 | if (!uh) | 266 | fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp)); |
269 | goto err; | ||
270 | |||
271 | fail = lowpan_fetch_skb(skb, &tmp, 1); | ||
272 | 267 | ||
273 | if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { | 268 | if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { |
274 | pr_debug("UDP header uncompression\n"); | 269 | pr_debug("UDP header uncompression\n"); |
275 | switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { | 270 | switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { |
276 | case LOWPAN_NHC_UDP_CS_P_00: | 271 | case LOWPAN_NHC_UDP_CS_P_00: |
277 | fail |= lowpan_fetch_skb(skb, &uh->source, 2); | 272 | fail |= lowpan_fetch_skb(skb, &uh->source, |
278 | fail |= lowpan_fetch_skb(skb, &uh->dest, 2); | 273 | sizeof(uh->source)); |
274 | fail |= lowpan_fetch_skb(skb, &uh->dest, | ||
275 | sizeof(uh->dest)); | ||
279 | break; | 276 | break; |
280 | case LOWPAN_NHC_UDP_CS_P_01: | 277 | case LOWPAN_NHC_UDP_CS_P_01: |
281 | fail |= lowpan_fetch_skb(skb, &uh->source, 2); | 278 | fail |= lowpan_fetch_skb(skb, &uh->source, |
282 | fail |= lowpan_fetch_skb(skb, &val, 1); | 279 | sizeof(uh->source)); |
280 | fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); | ||
283 | uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); | 281 | uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); |
284 | break; | 282 | break; |
285 | case LOWPAN_NHC_UDP_CS_P_10: | 283 | case LOWPAN_NHC_UDP_CS_P_10: |
286 | fail |= lowpan_fetch_skb(skb, &val, 1); | 284 | fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); |
287 | uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); | 285 | uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); |
288 | fail |= lowpan_fetch_skb(skb, &uh->dest, 2); | 286 | fail |= lowpan_fetch_skb(skb, &uh->dest, |
287 | sizeof(uh->dest)); | ||
289 | break; | 288 | break; |
290 | case LOWPAN_NHC_UDP_CS_P_11: | 289 | case LOWPAN_NHC_UDP_CS_P_11: |
291 | fail |= lowpan_fetch_skb(skb, &val, 1); | 290 | fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); |
292 | uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + | 291 | uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + |
293 | (val >> 4)); | 292 | (val >> 4)); |
294 | uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + | 293 | uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + |
@@ -307,10 +306,11 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | |||
307 | pr_debug_ratelimited("checksum elided currently not supported\n"); | 306 | pr_debug_ratelimited("checksum elided currently not supported\n"); |
308 | goto err; | 307 | goto err; |
309 | } else { | 308 | } else { |
310 | fail |= lowpan_fetch_skb(skb, &uh->check, 2); | 309 | fail |= lowpan_fetch_skb(skb, &uh->check, |
310 | sizeof(uh->check)); | ||
311 | } | 311 | } |
312 | 312 | ||
313 | /* UDP lenght needs to be infered from the lower layers | 313 | /* UDP length needs to be infered from the lower layers |
314 | * here, we obtain the hint from the remaining size of the | 314 | * here, we obtain the hint from the remaining size of the |
315 | * frame | 315 | * frame |
316 | */ | 316 | */ |
@@ -333,9 +333,8 @@ err: | |||
333 | static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; | 333 | static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; |
334 | 334 | ||
335 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | 335 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, |
336 | const u8 *saddr, const u8 saddr_type, | 336 | const u8 *saddr, const u8 saddr_type, const u8 saddr_len, |
337 | const u8 saddr_len, const u8 *daddr, | 337 | const u8 *daddr, const u8 daddr_type, const u8 daddr_len, |
338 | const u8 daddr_type, const u8 daddr_len, | ||
339 | u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) | 338 | u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) |
340 | { | 339 | { |
341 | struct ipv6hdr hdr = {}; | 340 | struct ipv6hdr hdr = {}; |
@@ -348,7 +347,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
348 | /* another if the CID flag is set */ | 347 | /* another if the CID flag is set */ |
349 | if (iphc1 & LOWPAN_IPHC_CID) { | 348 | if (iphc1 & LOWPAN_IPHC_CID) { |
350 | pr_debug("CID flag is set, increase header with one\n"); | 349 | pr_debug("CID flag is set, increase header with one\n"); |
351 | if (lowpan_fetch_skb_u8(skb, &num_context)) | 350 | if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) |
352 | goto drop; | 351 | goto drop; |
353 | } | 352 | } |
354 | 353 | ||
@@ -360,7 +359,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
360 | * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) | 359 | * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) |
361 | */ | 360 | */ |
362 | case 0: /* 00b */ | 361 | case 0: /* 00b */ |
363 | if (lowpan_fetch_skb_u8(skb, &tmp)) | 362 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
364 | goto drop; | 363 | goto drop; |
365 | 364 | ||
366 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); | 365 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); |
@@ -373,7 +372,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
373 | * ECN + DSCP (1 byte), Flow Label is elided | 372 | * ECN + DSCP (1 byte), Flow Label is elided |
374 | */ | 373 | */ |
375 | case 2: /* 10b */ | 374 | case 2: /* 10b */ |
376 | if (lowpan_fetch_skb_u8(skb, &tmp)) | 375 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
377 | goto drop; | 376 | goto drop; |
378 | 377 | ||
379 | hdr.priority = ((tmp >> 2) & 0x0f); | 378 | hdr.priority = ((tmp >> 2) & 0x0f); |
@@ -383,7 +382,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
383 | * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided | 382 | * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided |
384 | */ | 383 | */ |
385 | case 1: /* 01b */ | 384 | case 1: /* 01b */ |
386 | if (lowpan_fetch_skb_u8(skb, &tmp)) | 385 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
387 | goto drop; | 386 | goto drop; |
388 | 387 | ||
389 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); | 388 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); |
@@ -400,7 +399,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
400 | /* Next Header */ | 399 | /* Next Header */ |
401 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | 400 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { |
402 | /* Next header is carried inline */ | 401 | /* Next header is carried inline */ |
403 | if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) | 402 | if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) |
404 | goto drop; | 403 | goto drop; |
405 | 404 | ||
406 | pr_debug("NH flag is set, next header carried inline: %02x\n", | 405 | pr_debug("NH flag is set, next header carried inline: %02x\n", |
@@ -411,7 +410,8 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
411 | if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) { | 410 | if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) { |
412 | hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; | 411 | hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; |
413 | } else { | 412 | } else { |
414 | if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) | 413 | if (lowpan_fetch_skb(skb, &hdr.hop_limit, |
414 | sizeof(hdr.hop_limit))) | ||
415 | goto drop; | 415 | goto drop; |
416 | } | 416 | } |
417 | 417 | ||
@@ -421,8 +421,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
421 | if (iphc1 & LOWPAN_IPHC_SAC) { | 421 | if (iphc1 & LOWPAN_IPHC_SAC) { |
422 | /* Source address context based uncompression */ | 422 | /* Source address context based uncompression */ |
423 | pr_debug("SAC bit is set. Handle context based source address.\n"); | 423 | pr_debug("SAC bit is set. Handle context based source address.\n"); |
424 | err = uncompress_context_based_src_addr( | 424 | err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp); |
425 | skb, &hdr.saddr, tmp); | ||
426 | } else { | 425 | } else { |
427 | /* Source address uncompression */ | 426 | /* Source address uncompression */ |
428 | pr_debug("source address stateless compression\n"); | 427 | pr_debug("source address stateless compression\n"); |
@@ -443,8 +442,9 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
443 | pr_debug("dest: context-based mcast compression\n"); | 442 | pr_debug("dest: context-based mcast compression\n"); |
444 | /* TODO: implement this */ | 443 | /* TODO: implement this */ |
445 | } else { | 444 | } else { |
446 | err = lowpan_uncompress_multicast_daddr( | 445 | err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr, |
447 | skb, &hdr.daddr, tmp); | 446 | tmp); |
447 | |||
448 | if (err) | 448 | if (err) |
449 | goto drop; | 449 | goto drop; |
450 | } | 450 | } |
@@ -497,8 +497,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
497 | hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, | 497 | hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, |
498 | hdr.hop_limit, &hdr.daddr); | 498 | hdr.hop_limit, &hdr.daddr); |
499 | 499 | ||
500 | raw_dump_table(__func__, "raw header dump", | 500 | raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); |
501 | (u8 *)&hdr, sizeof(hdr)); | ||
502 | 501 | ||
503 | return skb_deliver(skb, &hdr, dev, deliver_skb); | 502 | return skb_deliver(skb, &hdr, dev, deliver_skb); |
504 | 503 | ||
@@ -508,7 +507,7 @@ drop: | |||
508 | } | 507 | } |
509 | EXPORT_SYMBOL_GPL(lowpan_process_data); | 508 | EXPORT_SYMBOL_GPL(lowpan_process_data); |
510 | 509 | ||
511 | static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, | 510 | static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, |
512 | const struct in6_addr *ipaddr, | 511 | const struct in6_addr *ipaddr, |
513 | const unsigned char *lladdr) | 512 | const unsigned char *lladdr) |
514 | { | 513 | { |
@@ -519,24 +518,22 @@ static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, | |||
519 | pr_debug("address compression 0 bits\n"); | 518 | pr_debug("address compression 0 bits\n"); |
520 | } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { | 519 | } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { |
521 | /* compress IID to 16 bits xxxx::XXXX */ | 520 | /* compress IID to 16 bits xxxx::XXXX */ |
522 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); | 521 | lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2); |
523 | *hc06_ptr += 2; | ||
524 | val = 2; /* 16-bits */ | 522 | val = 2; /* 16-bits */ |
525 | raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", | 523 | raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", |
526 | *hc06_ptr - 2, 2); | 524 | *hc_ptr - 2, 2); |
527 | } else { | 525 | } else { |
528 | /* do not compress IID => xxxx::IID */ | 526 | /* do not compress IID => xxxx::IID */ |
529 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); | 527 | lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8); |
530 | *hc06_ptr += 8; | ||
531 | val = 1; /* 64-bits */ | 528 | val = 1; /* 64-bits */ |
532 | raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", | 529 | raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", |
533 | *hc06_ptr - 8, 8); | 530 | *hc_ptr - 8, 8); |
534 | } | 531 | } |
535 | 532 | ||
536 | return rol8(val, shift); | 533 | return rol8(val, shift); |
537 | } | 534 | } |
538 | 535 | ||
539 | static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) | 536 | static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) |
540 | { | 537 | { |
541 | struct udphdr *uh = udp_hdr(skb); | 538 | struct udphdr *uh = udp_hdr(skb); |
542 | u8 tmp; | 539 | u8 tmp; |
@@ -548,46 +545,46 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) | |||
548 | pr_debug("UDP header: both ports compression to 4 bits\n"); | 545 | pr_debug("UDP header: both ports compression to 4 bits\n"); |
549 | /* compression value */ | 546 | /* compression value */ |
550 | tmp = LOWPAN_NHC_UDP_CS_P_11; | 547 | tmp = LOWPAN_NHC_UDP_CS_P_11; |
551 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 548 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
552 | /* source and destination port */ | 549 | /* source and destination port */ |
553 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + | 550 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + |
554 | ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); | 551 | ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); |
555 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 552 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
556 | } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == | 553 | } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == |
557 | LOWPAN_NHC_UDP_8BIT_PORT) { | 554 | LOWPAN_NHC_UDP_8BIT_PORT) { |
558 | pr_debug("UDP header: remove 8 bits of dest\n"); | 555 | pr_debug("UDP header: remove 8 bits of dest\n"); |
559 | /* compression value */ | 556 | /* compression value */ |
560 | tmp = LOWPAN_NHC_UDP_CS_P_01; | 557 | tmp = LOWPAN_NHC_UDP_CS_P_01; |
561 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 558 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
562 | /* source port */ | 559 | /* source port */ |
563 | lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); | 560 | lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source)); |
564 | /* destination port */ | 561 | /* destination port */ |
565 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; | 562 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; |
566 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 563 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
567 | } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == | 564 | } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == |
568 | LOWPAN_NHC_UDP_8BIT_PORT) { | 565 | LOWPAN_NHC_UDP_8BIT_PORT) { |
569 | pr_debug("UDP header: remove 8 bits of source\n"); | 566 | pr_debug("UDP header: remove 8 bits of source\n"); |
570 | /* compression value */ | 567 | /* compression value */ |
571 | tmp = LOWPAN_NHC_UDP_CS_P_10; | 568 | tmp = LOWPAN_NHC_UDP_CS_P_10; |
572 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 569 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
573 | /* source port */ | 570 | /* source port */ |
574 | tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; | 571 | tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; |
575 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 572 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
576 | /* destination port */ | 573 | /* destination port */ |
577 | lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); | 574 | lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest)); |
578 | } else { | 575 | } else { |
579 | pr_debug("UDP header: can't compress\n"); | 576 | pr_debug("UDP header: can't compress\n"); |
580 | /* compression value */ | 577 | /* compression value */ |
581 | tmp = LOWPAN_NHC_UDP_CS_P_00; | 578 | tmp = LOWPAN_NHC_UDP_CS_P_00; |
582 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 579 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
583 | /* source port */ | 580 | /* source port */ |
584 | lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); | 581 | lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source)); |
585 | /* destination port */ | 582 | /* destination port */ |
586 | lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); | 583 | lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest)); |
587 | } | 584 | } |
588 | 585 | ||
589 | /* checksum is always inline */ | 586 | /* checksum is always inline */ |
590 | lowpan_push_hc_data(hc06_ptr, &uh->check, sizeof(uh->check)); | 587 | lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check)); |
591 | 588 | ||
592 | /* skip the UDP header */ | 589 | /* skip the UDP header */ |
593 | skb_pull(skb, sizeof(struct udphdr)); | 590 | skb_pull(skb, sizeof(struct udphdr)); |
@@ -597,15 +594,16 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
597 | unsigned short type, const void *_daddr, | 594 | unsigned short type, const void *_daddr, |
598 | const void *_saddr, unsigned int len) | 595 | const void *_saddr, unsigned int len) |
599 | { | 596 | { |
600 | u8 tmp, iphc0, iphc1, *hc06_ptr; | 597 | u8 tmp, iphc0, iphc1, *hc_ptr; |
601 | struct ipv6hdr *hdr; | 598 | struct ipv6hdr *hdr; |
602 | u8 head[100] = {}; | 599 | u8 head[100] = {}; |
600 | int addr_type; | ||
603 | 601 | ||
604 | if (type != ETH_P_IPV6) | 602 | if (type != ETH_P_IPV6) |
605 | return -EINVAL; | 603 | return -EINVAL; |
606 | 604 | ||
607 | hdr = ipv6_hdr(skb); | 605 | hdr = ipv6_hdr(skb); |
608 | hc06_ptr = head + 2; | 606 | hc_ptr = head + 2; |
609 | 607 | ||
610 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" | 608 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" |
611 | "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", | 609 | "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", |
@@ -630,8 +628,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
630 | raw_dump_inline(__func__, "daddr", | 628 | raw_dump_inline(__func__, "daddr", |
631 | (unsigned char *)_daddr, IEEE802154_ADDR_LEN); | 629 | (unsigned char *)_daddr, IEEE802154_ADDR_LEN); |
632 | 630 | ||
633 | raw_dump_table(__func__, | 631 | raw_dump_table(__func__, "sending raw skb network uncompressed packet", |
634 | "sending raw skb network uncompressed packet", | ||
635 | skb->data, skb->len); | 632 | skb->data, skb->len); |
636 | 633 | ||
637 | /* Traffic class, flow label | 634 | /* Traffic class, flow label |
@@ -640,7 +637,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
640 | * class depends on the presence of version and flow label | 637 | * class depends on the presence of version and flow label |
641 | */ | 638 | */ |
642 | 639 | ||
643 | /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ | 640 | /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */ |
644 | tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); | 641 | tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); |
645 | tmp = ((tmp & 0x03) << 6) | (tmp >> 2); | 642 | tmp = ((tmp & 0x03) << 6) | (tmp >> 2); |
646 | 643 | ||
@@ -654,8 +651,8 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
654 | iphc0 |= LOWPAN_IPHC_TC_C; | 651 | iphc0 |= LOWPAN_IPHC_TC_C; |
655 | } else { | 652 | } else { |
656 | /* compress only the flow label */ | 653 | /* compress only the flow label */ |
657 | *hc06_ptr = tmp; | 654 | *hc_ptr = tmp; |
658 | hc06_ptr += 1; | 655 | hc_ptr += 1; |
659 | } | 656 | } |
660 | } else { | 657 | } else { |
661 | /* Flow label cannot be compressed */ | 658 | /* Flow label cannot be compressed */ |
@@ -663,15 +660,15 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
663 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | 660 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { |
664 | /* compress only traffic class */ | 661 | /* compress only traffic class */ |
665 | iphc0 |= LOWPAN_IPHC_TC_C; | 662 | iphc0 |= LOWPAN_IPHC_TC_C; |
666 | *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); | 663 | *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); |
667 | memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); | 664 | memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2); |
668 | hc06_ptr += 3; | 665 | hc_ptr += 3; |
669 | } else { | 666 | } else { |
670 | /* compress nothing */ | 667 | /* compress nothing */ |
671 | memcpy(hc06_ptr, hdr, 4); | 668 | memcpy(hc_ptr, hdr, 4); |
672 | /* replace the top byte with new ECN | DSCP format */ | 669 | /* replace the top byte with new ECN | DSCP format */ |
673 | *hc06_ptr = tmp; | 670 | *hc_ptr = tmp; |
674 | hc06_ptr += 4; | 671 | hc_ptr += 4; |
675 | } | 672 | } |
676 | } | 673 | } |
677 | 674 | ||
@@ -681,10 +678,9 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
681 | if (hdr->nexthdr == UIP_PROTO_UDP) | 678 | if (hdr->nexthdr == UIP_PROTO_UDP) |
682 | iphc0 |= LOWPAN_IPHC_NH_C; | 679 | iphc0 |= LOWPAN_IPHC_NH_C; |
683 | 680 | ||
684 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | 681 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) |
685 | *hc06_ptr = hdr->nexthdr; | 682 | lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr, |
686 | hc06_ptr += 1; | 683 | sizeof(hdr->nexthdr)); |
687 | } | ||
688 | 684 | ||
689 | /* Hop limit | 685 | /* Hop limit |
690 | * if 1: compress, encoding is 01 | 686 | * if 1: compress, encoding is 01 |
@@ -703,84 +699,86 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
703 | iphc0 |= LOWPAN_IPHC_TTL_255; | 699 | iphc0 |= LOWPAN_IPHC_TTL_255; |
704 | break; | 700 | break; |
705 | default: | 701 | default: |
706 | *hc06_ptr = hdr->hop_limit; | 702 | lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit, |
707 | hc06_ptr += 1; | 703 | sizeof(hdr->hop_limit)); |
708 | break; | ||
709 | } | 704 | } |
710 | 705 | ||
706 | addr_type = ipv6_addr_type(&hdr->saddr); | ||
711 | /* source address compression */ | 707 | /* source address compression */ |
712 | if (is_addr_unspecified(&hdr->saddr)) { | 708 | if (addr_type == IPV6_ADDR_ANY) { |
713 | pr_debug("source address is unspecified, setting SAC\n"); | 709 | pr_debug("source address is unspecified, setting SAC\n"); |
714 | iphc1 |= LOWPAN_IPHC_SAC; | 710 | iphc1 |= LOWPAN_IPHC_SAC; |
715 | /* TODO: context lookup */ | ||
716 | } else if (is_addr_link_local(&hdr->saddr)) { | ||
717 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | ||
718 | LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr); | ||
719 | pr_debug("source address unicast link-local %pI6c " | ||
720 | "iphc1 0x%02x\n", &hdr->saddr, iphc1); | ||
721 | } else { | 711 | } else { |
722 | pr_debug("send the full source address\n"); | 712 | if (addr_type & IPV6_ADDR_LINKLOCAL) { |
723 | memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); | 713 | iphc1 |= lowpan_compress_addr_64(&hc_ptr, |
724 | hc06_ptr += 16; | 714 | LOWPAN_IPHC_SAM_BIT, |
715 | &hdr->saddr, _saddr); | ||
716 | pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n", | ||
717 | &hdr->saddr, iphc1); | ||
718 | } else { | ||
719 | pr_debug("send the full source address\n"); | ||
720 | lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16); | ||
721 | } | ||
725 | } | 722 | } |
726 | 723 | ||
724 | addr_type = ipv6_addr_type(&hdr->daddr); | ||
727 | /* destination address compression */ | 725 | /* destination address compression */ |
728 | if (is_addr_mcast(&hdr->daddr)) { | 726 | if (addr_type & IPV6_ADDR_MULTICAST) { |
729 | pr_debug("destination address is multicast: "); | 727 | pr_debug("destination address is multicast: "); |
730 | iphc1 |= LOWPAN_IPHC_M; | 728 | iphc1 |= LOWPAN_IPHC_M; |
731 | if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { | 729 | if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { |
732 | pr_debug("compressed to 1 octet\n"); | 730 | pr_debug("compressed to 1 octet\n"); |
733 | iphc1 |= LOWPAN_IPHC_DAM_11; | 731 | iphc1 |= LOWPAN_IPHC_DAM_11; |
734 | /* use last byte */ | 732 | /* use last byte */ |
735 | *hc06_ptr = hdr->daddr.s6_addr[15]; | 733 | lowpan_push_hc_data(&hc_ptr, |
736 | hc06_ptr += 1; | 734 | &hdr->daddr.s6_addr[15], 1); |
737 | } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { | 735 | } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { |
738 | pr_debug("compressed to 4 octets\n"); | 736 | pr_debug("compressed to 4 octets\n"); |
739 | iphc1 |= LOWPAN_IPHC_DAM_10; | 737 | iphc1 |= LOWPAN_IPHC_DAM_10; |
740 | /* second byte + the last three */ | 738 | /* second byte + the last three */ |
741 | *hc06_ptr = hdr->daddr.s6_addr[1]; | 739 | lowpan_push_hc_data(&hc_ptr, |
742 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); | 740 | &hdr->daddr.s6_addr[1], 1); |
743 | hc06_ptr += 4; | 741 | lowpan_push_hc_data(&hc_ptr, |
742 | &hdr->daddr.s6_addr[13], 3); | ||
744 | } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { | 743 | } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { |
745 | pr_debug("compressed to 6 octets\n"); | 744 | pr_debug("compressed to 6 octets\n"); |
746 | iphc1 |= LOWPAN_IPHC_DAM_01; | 745 | iphc1 |= LOWPAN_IPHC_DAM_01; |
747 | /* second byte + the last five */ | 746 | /* second byte + the last five */ |
748 | *hc06_ptr = hdr->daddr.s6_addr[1]; | 747 | lowpan_push_hc_data(&hc_ptr, |
749 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); | 748 | &hdr->daddr.s6_addr[1], 1); |
750 | hc06_ptr += 6; | 749 | lowpan_push_hc_data(&hc_ptr, |
750 | &hdr->daddr.s6_addr[11], 5); | ||
751 | } else { | 751 | } else { |
752 | pr_debug("using full address\n"); | 752 | pr_debug("using full address\n"); |
753 | iphc1 |= LOWPAN_IPHC_DAM_00; | 753 | iphc1 |= LOWPAN_IPHC_DAM_00; |
754 | memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); | 754 | lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); |
755 | hc06_ptr += 16; | ||
756 | } | 755 | } |
757 | } else { | 756 | } else { |
758 | /* TODO: context lookup */ | 757 | if (addr_type & IPV6_ADDR_LINKLOCAL) { |
759 | if (is_addr_link_local(&hdr->daddr)) { | 758 | /* TODO: context lookup */ |
760 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | 759 | iphc1 |= lowpan_compress_addr_64(&hc_ptr, |
761 | LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); | 760 | LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); |
762 | pr_debug("dest address unicast link-local %pI6c " | 761 | pr_debug("dest address unicast link-local %pI6c " |
763 | "iphc1 0x%02x\n", &hdr->daddr, iphc1); | 762 | "iphc1 0x%02x\n", &hdr->daddr, iphc1); |
764 | } else { | 763 | } else { |
765 | pr_debug("dest address unicast %pI6c\n", &hdr->daddr); | 764 | pr_debug("dest address unicast %pI6c\n", &hdr->daddr); |
766 | memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); | 765 | lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); |
767 | hc06_ptr += 16; | ||
768 | } | 766 | } |
769 | } | 767 | } |
770 | 768 | ||
771 | /* UDP header compression */ | 769 | /* UDP header compression */ |
772 | if (hdr->nexthdr == UIP_PROTO_UDP) | 770 | if (hdr->nexthdr == UIP_PROTO_UDP) |
773 | compress_udp_header(&hc06_ptr, skb); | 771 | compress_udp_header(&hc_ptr, skb); |
774 | 772 | ||
775 | head[0] = iphc0; | 773 | head[0] = iphc0; |
776 | head[1] = iphc1; | 774 | head[1] = iphc1; |
777 | 775 | ||
778 | skb_pull(skb, sizeof(struct ipv6hdr)); | 776 | skb_pull(skb, sizeof(struct ipv6hdr)); |
779 | skb_reset_transport_header(skb); | 777 | skb_reset_transport_header(skb); |
780 | memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); | 778 | memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head); |
781 | skb_reset_network_header(skb); | 779 | skb_reset_network_header(skb); |
782 | 780 | ||
783 | pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len); | 781 | pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len); |
784 | 782 | ||
785 | raw_dump_table(__func__, "raw skb data dump compressed", | 783 | raw_dump_table(__func__, "raw skb data dump compressed", |
786 | skb->data, skb->len); | 784 | skb->data, skb->len); |