Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

6lowpan: Moving generic compression code into 6lowpan_iphc.c

Because the IEEE 802154 and Bluetooth share the IP header compression
and uncompression code, the common code is moved to 6lowpan_iphc.c
file.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Acked-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Jukka Rissanen and committed by
Marcel Holtmann
8df8c56a 71fb4197

+875 -719
+35 -718
net/ieee802154/6lowpan.c
··· 62 62 63 63 #include "6lowpan.h" 64 64 65 - /* TTL uncompression values */ 66 - static const u8 lowpan_ttl_values[] = {0, 1, 64, 255}; 67 - 68 65 static LIST_HEAD(lowpan_devices); 69 66 70 67 /* private device info */ ··· 132 135 #endif /* DEBUG */ 133 136 } 134 137 135 - static u8 136 - lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr, 137 - const unsigned char *lladdr) 138 - { 139 - u8 val = 0; 140 - 141 - if (is_addr_mac_addr_based(ipaddr, lladdr)) 142 - val = 3; /* 0-bits */ 143 - else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 144 - /* compress IID to 16 bits xxxx::XXXX */ 145 - memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); 146 - *hc06_ptr += 2; 147 - val = 2; /* 16-bits */ 148 - } else { 149 - /* do not compress IID => xxxx::IID */ 150 - memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); 151 - *hc06_ptr += 8; 152 - val = 1; /* 64-bits */ 153 - } 154 - 155 - return rol8(val, shift); 156 - } 157 - 158 - /* 159 - * Uncompress address function for source and 160 - * destination address(non-multicast). 161 - * 162 - * address_mode is sam value or dam value. 163 - */ 164 - static int 165 - lowpan_uncompress_addr(struct sk_buff *skb, 166 - struct in6_addr *ipaddr, 167 - const u8 address_mode, 168 - const struct ieee802154_addr *lladdr) 169 - { 170 - bool fail; 171 - 172 - switch (address_mode) { 173 - case LOWPAN_IPHC_ADDR_00: 174 - /* for global link addresses */ 175 - fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 176 - break; 177 - case LOWPAN_IPHC_ADDR_01: 178 - /* fe:80::XXXX:XXXX:XXXX:XXXX */ 179 - ipaddr->s6_addr[0] = 0xFE; 180 - ipaddr->s6_addr[1] = 0x80; 181 - fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); 182 - break; 183 - case LOWPAN_IPHC_ADDR_02: 184 - /* fe:80::ff:fe00:XXXX */ 185 - ipaddr->s6_addr[0] = 0xFE; 186 - ipaddr->s6_addr[1] = 0x80; 187 - ipaddr->s6_addr[11] = 0xFF; 188 - ipaddr->s6_addr[12] = 0xFE; 189 - fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); 190 - break; 191 - case LOWPAN_IPHC_ADDR_03: 192 - fail = false; 193 - switch (lladdr->addr_type) { 194 - case IEEE802154_ADDR_LONG: 195 - /* fe:80::XXXX:XXXX:XXXX:XXXX 196 - * \_________________/ 197 - * hwaddr 198 - */ 199 - ipaddr->s6_addr[0] = 0xFE; 200 - ipaddr->s6_addr[1] = 0x80; 201 - memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr, 202 - IEEE802154_ADDR_LEN); 203 - /* second bit-flip (Universe/Local) 204 - * is done according RFC2464 205 - */ 206 - ipaddr->s6_addr[8] ^= 0x02; 207 - break; 208 - case IEEE802154_ADDR_SHORT: 209 - /* fe:80::ff:fe00:XXXX 210 - * \__/ 211 - * short_addr 212 - * 213 - * Universe/Local bit is zero. 214 - */ 215 - ipaddr->s6_addr[0] = 0xFE; 216 - ipaddr->s6_addr[1] = 0x80; 217 - ipaddr->s6_addr[11] = 0xFF; 218 - ipaddr->s6_addr[12] = 0xFE; 219 - ipaddr->s6_addr16[7] = htons(lladdr->short_addr); 220 - break; 221 - default: 222 - pr_debug("Invalid addr_type set\n"); 223 - return -EINVAL; 224 - } 225 - break; 226 - default: 227 - pr_debug("Invalid address mode value: 0x%x\n", address_mode); 228 - return -EINVAL; 229 - } 230 - 231 - if (fail) { 232 - pr_debug("Failed to fetch skb data\n"); 233 - return -EIO; 234 - } 235 - 236 - lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 addr is:\n", 237 - ipaddr->s6_addr, 16); 238 - 239 - return 0; 240 - } 241 - 242 - /* Uncompress address function for source context 243 - * based address(non-multicast). 244 - */ 245 - static int 246 - lowpan_uncompress_context_based_src_addr(struct sk_buff *skb, 247 - struct in6_addr *ipaddr, 248 - const u8 sam) 249 - { 250 - switch (sam) { 251 - case LOWPAN_IPHC_ADDR_00: 252 - /* unspec address :: 253 - * Do nothing, address is already :: 254 - */ 255 - break; 256 - case LOWPAN_IPHC_ADDR_01: 257 - /* TODO */ 258 - case LOWPAN_IPHC_ADDR_02: 259 - /* TODO */ 260 - case LOWPAN_IPHC_ADDR_03: 261 - /* TODO */ 262 - netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); 263 - return -EINVAL; 264 - default: 265 - pr_debug("Invalid sam value: 0x%x\n", sam); 266 - return -EINVAL; 267 - } 268 - 269 - lowpan_raw_dump_inline(NULL, 270 - "Reconstructed context based ipv6 src addr is:\n", 271 - ipaddr->s6_addr, 16); 272 - 273 - return 0; 274 - } 275 - 276 - /* Uncompress function for multicast destination address, 277 - * when M bit is set. 278 - */ 279 - static int 280 - lowpan_uncompress_multicast_daddr(struct sk_buff *skb, 281 - struct in6_addr *ipaddr, 282 - const u8 dam) 283 - { 284 - bool fail; 285 - 286 - switch (dam) { 287 - case LOWPAN_IPHC_DAM_00: 288 - /* 00: 128 bits. The full address 289 - * is carried in-line. 290 - */ 291 - fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 292 - break; 293 - case LOWPAN_IPHC_DAM_01: 294 - /* 01: 48 bits. The address takes 295 - * the form ffXX::00XX:XXXX:XXXX. 296 - */ 297 - ipaddr->s6_addr[0] = 0xFF; 298 - fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 299 - fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); 300 - break; 301 - case LOWPAN_IPHC_DAM_10: 302 - /* 10: 32 bits. The address takes 303 - * the form ffXX::00XX:XXXX. 304 - */ 305 - ipaddr->s6_addr[0] = 0xFF; 306 - fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 307 - fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); 308 - break; 309 - case LOWPAN_IPHC_DAM_11: 310 - /* 11: 8 bits. The address takes 311 - * the form ff02::00XX. 312 - */ 313 - ipaddr->s6_addr[0] = 0xFF; 314 - ipaddr->s6_addr[1] = 0x02; 315 - fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); 316 - break; 317 - default: 318 - pr_debug("DAM value has a wrong value: 0x%x\n", dam); 319 - return -EINVAL; 320 - } 321 - 322 - if (fail) { 323 - pr_debug("Failed to fetch skb data\n"); 324 - return -EIO; 325 - } 326 - 327 - lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n", 328 - ipaddr->s6_addr, 16); 329 - 330 - return 0; 331 - } 332 - 333 - static void 334 - lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) 335 - { 336 - struct udphdr *uh = udp_hdr(skb); 337 - 338 - if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) == 339 - LOWPAN_NHC_UDP_4BIT_PORT) && 340 - ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) == 341 - LOWPAN_NHC_UDP_4BIT_PORT)) { 342 - pr_debug("UDP header: both ports compression to 4 bits\n"); 343 - **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11; 344 - **(hc06_ptr + 1) = /* subtraction is faster */ 345 - (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) + 346 - ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4)); 347 - *hc06_ptr += 2; 348 - } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) == 349 - LOWPAN_NHC_UDP_8BIT_PORT) { 350 - pr_debug("UDP header: remove 8 bits of dest\n"); 351 - **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01; 352 - memcpy(*hc06_ptr + 1, &uh->source, 2); 353 - **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT); 354 - *hc06_ptr += 4; 355 - } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) == 356 - LOWPAN_NHC_UDP_8BIT_PORT) { 357 - pr_debug("UDP header: remove 8 bits of source\n"); 358 - **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10; 359 - memcpy(*hc06_ptr + 1, &uh->dest, 2); 360 - **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT); 361 - *hc06_ptr += 4; 362 - } else { 363 - pr_debug("UDP header: can't compress\n"); 364 - **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00; 365 - memcpy(*hc06_ptr + 1, &uh->source, 2); 366 - memcpy(*hc06_ptr + 3, &uh->dest, 2); 367 - *hc06_ptr += 5; 368 - } 369 - 370 - /* checksum is always inline */ 371 - memcpy(*hc06_ptr, &uh->check, 2); 372 - *hc06_ptr += 2; 373 - 374 - /* skip the UDP header */ 375 - skb_pull(skb, sizeof(struct udphdr)); 376 - } 377 - 378 - static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) 379 - { 380 - if (unlikely(!pskb_may_pull(skb, 1))) 381 - return -EINVAL; 382 - 383 - *val = skb->data[0]; 384 - skb_pull(skb, 1); 385 - 386 - return 0; 387 - } 388 - 389 - static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val) 390 - { 391 - if (unlikely(!pskb_may_pull(skb, 2))) 392 - return -EINVAL; 393 - 394 - *val = (skb->data[0] << 8) | skb->data[1]; 395 - skb_pull(skb, 2); 396 - 397 - return 0; 398 - } 399 - 400 - static int 401 - lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) 402 - { 403 - u8 tmp; 404 - 405 - if (!uh) 406 - goto err; 407 - 408 - if (lowpan_fetch_skb_u8(skb, &tmp)) 409 - goto err; 410 - 411 - if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { 412 - pr_debug("UDP header uncompression\n"); 413 - switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { 414 - case LOWPAN_NHC_UDP_CS_P_00: 415 - memcpy(&uh->source, &skb->data[0], 2); 416 - memcpy(&uh->dest, &skb->data[2], 2); 417 - skb_pull(skb, 4); 418 - break; 419 - case LOWPAN_NHC_UDP_CS_P_01: 420 - memcpy(&uh->source, &skb->data[0], 2); 421 - uh->dest = 422 - skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT; 423 - skb_pull(skb, 3); 424 - break; 425 - case LOWPAN_NHC_UDP_CS_P_10: 426 - uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT; 427 - memcpy(&uh->dest, &skb->data[1], 2); 428 - skb_pull(skb, 3); 429 - break; 430 - case LOWPAN_NHC_UDP_CS_P_11: 431 - uh->source = 432 - LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4); 433 - uh->dest = 434 - LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f); 435 - skb_pull(skb, 1); 436 - break; 437 - default: 438 - pr_debug("ERROR: unknown UDP format\n"); 439 - goto err; 440 - } 441 - 442 - pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", 443 - uh->source, uh->dest); 444 - 445 - /* copy checksum */ 446 - memcpy(&uh->check, &skb->data[0], 2); 447 - skb_pull(skb, 2); 448 - 449 - /* 450 - * UDP lenght needs to be infered from the lower layers 451 - * here, we obtain the hint from the remaining size of the 452 - * frame 453 - */ 454 - uh->len = htons(skb->len + sizeof(struct udphdr)); 455 - pr_debug("uncompressed UDP length: src = %d", uh->len); 456 - } else { 457 - pr_debug("ERROR: unsupported NH format\n"); 458 - goto err; 459 - } 460 - 461 - return 0; 462 - err: 463 - return -EINVAL; 464 - } 465 - 466 138 static int lowpan_header_create(struct sk_buff *skb, 467 139 struct net_device *dev, 468 140 unsigned short type, const void *_daddr, 469 141 const void *_saddr, unsigned int len) 470 142 { 471 - u8 tmp, iphc0, iphc1, *hc06_ptr; 472 143 struct ipv6hdr *hdr; 473 144 const u8 *saddr = _saddr; 474 145 const u8 *daddr = _daddr; 475 - u8 head[100]; 476 146 struct ieee802154_addr sa, da; 477 147 478 148 /* TODO: ··· 149 485 return 0; 150 486 151 487 hdr = ipv6_hdr(skb); 152 - hc06_ptr = head + 2; 153 - 154 - pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 155 - "\tnexthdr = 0x%02x\n\thop_lim = %d\n", hdr->version, 156 - ntohs(hdr->payload_len), hdr->nexthdr, hdr->hop_limit); 157 - 158 - lowpan_raw_dump_table(__func__, "raw skb network header dump", 159 - skb_network_header(skb), sizeof(struct ipv6hdr)); 160 488 161 489 if (!saddr) 162 490 saddr = dev->dev_addr; 163 491 164 492 lowpan_raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8); 165 - 166 - /* 167 - * As we copy some bit-length fields, in the IPHC encoding bytes, 168 - * we sometimes use |= 169 - * If the field is 0, and the current bit value in memory is 1, 170 - * this does not work. We therefore reset the IPHC encoding here 171 - */ 172 - iphc0 = LOWPAN_DISPATCH_IPHC; 173 - iphc1 = 0; 174 - 175 - /* TODO: context lookup */ 176 - 177 493 lowpan_raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8); 178 494 179 - /* 180 - * Traffic class, flow label 181 - * If flow label is 0, compress it. If traffic class is 0, compress it 182 - * We have to process both in the same time as the offset of traffic 183 - * class depends on the presence of version and flow label 184 - */ 185 - 186 - /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ 187 - tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 188 - tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 189 - 190 - if (((hdr->flow_lbl[0] & 0x0F) == 0) && 191 - (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { 192 - /* flow label can be compressed */ 193 - iphc0 |= LOWPAN_IPHC_FL_C; 194 - if ((hdr->priority == 0) && 195 - ((hdr->flow_lbl[0] & 0xF0) == 0)) { 196 - /* compress (elide) all */ 197 - iphc0 |= LOWPAN_IPHC_TC_C; 198 - } else { 199 - /* compress only the flow label */ 200 - *hc06_ptr = tmp; 201 - hc06_ptr += 1; 202 - } 203 - } else { 204 - /* Flow label cannot be compressed */ 205 - if ((hdr->priority == 0) && 206 - ((hdr->flow_lbl[0] & 0xF0) == 0)) { 207 - /* compress only traffic class */ 208 - iphc0 |= LOWPAN_IPHC_TC_C; 209 - *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 210 - memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); 211 - hc06_ptr += 3; 212 - } else { 213 - /* compress nothing */ 214 - memcpy(hc06_ptr, &hdr, 4); 215 - /* replace the top byte with new ECN | DSCP format */ 216 - *hc06_ptr = tmp; 217 - hc06_ptr += 4; 218 - } 219 - } 220 - 221 - /* NOTE: payload length is always compressed */ 222 - 223 - /* Next Header is compress if UDP */ 224 - if (hdr->nexthdr == UIP_PROTO_UDP) 225 - iphc0 |= LOWPAN_IPHC_NH_C; 226 - 227 - if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 228 - *hc06_ptr = hdr->nexthdr; 229 - hc06_ptr += 1; 230 - } 231 - 232 - /* 233 - * Hop limit 234 - * if 1: compress, encoding is 01 235 - * if 64: compress, encoding is 10 236 - * if 255: compress, encoding is 11 237 - * else do not compress 238 - */ 239 - switch (hdr->hop_limit) { 240 - case 1: 241 - iphc0 |= LOWPAN_IPHC_TTL_1; 242 - break; 243 - case 64: 244 - iphc0 |= LOWPAN_IPHC_TTL_64; 245 - break; 246 - case 255: 247 - iphc0 |= LOWPAN_IPHC_TTL_255; 248 - break; 249 - default: 250 - *hc06_ptr = hdr->hop_limit; 251 - hc06_ptr += 1; 252 - break; 253 - } 254 - 255 - /* source address compression */ 256 - if (is_addr_unspecified(&hdr->saddr)) { 257 - pr_debug("source address is unspecified, setting SAC\n"); 258 - iphc1 |= LOWPAN_IPHC_SAC; 259 - /* TODO: context lookup */ 260 - } else if (is_addr_link_local(&hdr->saddr)) { 261 - pr_debug("source address is link-local\n"); 262 - iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 263 - LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr); 264 - } else { 265 - pr_debug("send the full source address\n"); 266 - memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); 267 - hc06_ptr += 16; 268 - } 269 - 270 - /* destination address compression */ 271 - if (is_addr_mcast(&hdr->daddr)) { 272 - pr_debug("destination address is multicast: "); 273 - iphc1 |= LOWPAN_IPHC_M; 274 - if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 275 - pr_debug("compressed to 1 octet\n"); 276 - iphc1 |= LOWPAN_IPHC_DAM_11; 277 - /* use last byte */ 278 - *hc06_ptr = hdr->daddr.s6_addr[15]; 279 - hc06_ptr += 1; 280 - } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 281 - pr_debug("compressed to 4 octets\n"); 282 - iphc1 |= LOWPAN_IPHC_DAM_10; 283 - /* second byte + the last three */ 284 - *hc06_ptr = hdr->daddr.s6_addr[1]; 285 - memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); 286 - hc06_ptr += 4; 287 - } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 288 - pr_debug("compressed to 6 octets\n"); 289 - iphc1 |= LOWPAN_IPHC_DAM_01; 290 - /* second byte + the last five */ 291 - *hc06_ptr = hdr->daddr.s6_addr[1]; 292 - memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); 293 - hc06_ptr += 6; 294 - } else { 295 - pr_debug("using full address\n"); 296 - iphc1 |= LOWPAN_IPHC_DAM_00; 297 - memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); 298 - hc06_ptr += 16; 299 - } 300 - } else { 301 - /* TODO: context lookup */ 302 - if (is_addr_link_local(&hdr->daddr)) { 303 - pr_debug("dest address is unicast and link-local\n"); 304 - iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 305 - LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr); 306 - } else { 307 - pr_debug("dest address is unicast: using full one\n"); 308 - memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); 309 - hc06_ptr += 16; 310 - } 311 - } 312 - 313 - /* UDP header compression */ 314 - if (hdr->nexthdr == UIP_PROTO_UDP) 315 - lowpan_compress_udp_header(&hc06_ptr, skb); 316 - 317 - head[0] = iphc0; 318 - head[1] = iphc1; 319 - 320 - skb_pull(skb, sizeof(struct ipv6hdr)); 321 - skb_reset_transport_header(skb); 322 - memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); 323 - skb_reset_network_header(skb); 324 - 325 - lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data, 326 - skb->len); 495 + lowpan_header_compress(skb, dev, type, daddr, saddr, len); 327 496 328 497 /* 329 498 * NOTE1: I'm still unsure about the fact that compression and WPAN ··· 168 671 * from MAC subif of the 'dev' and 'real_dev' network devices, but 169 672 * this isn't implemented in mainline yet, so currently we assign 0xff 170 673 */ 171 - { 172 - mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA; 173 - mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); 674 + mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA; 675 + mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); 174 676 175 - /* prepare wpan address data */ 176 - sa.addr_type = IEEE802154_ADDR_LONG; 177 - sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 677 + /* prepare wpan address data */ 678 + sa.addr_type = IEEE802154_ADDR_LONG; 679 + sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 178 680 179 - memcpy(&(sa.hwaddr), saddr, 8); 180 - /* intra-PAN communications */ 181 - da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 681 + memcpy(&(sa.hwaddr), saddr, 8); 682 + /* intra-PAN communications */ 683 + da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 182 684 183 - /* 184 - * if the destination address is the broadcast address, use the 185 - * corresponding short address 186 - */ 187 - if (lowpan_is_addr_broadcast(daddr)) { 188 - da.addr_type = IEEE802154_ADDR_SHORT; 189 - da.short_addr = IEEE802154_ADDR_BROADCAST; 190 - } else { 191 - da.addr_type = IEEE802154_ADDR_LONG; 192 - memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); 685 + /* 686 + * if the destination address is the broadcast address, use the 687 + * corresponding short address 688 + */ 689 + if (lowpan_is_addr_broadcast(daddr)) { 690 + da.addr_type = IEEE802154_ADDR_SHORT; 691 + da.short_addr = IEEE802154_ADDR_BROADCAST; 692 + } else { 693 + da.addr_type = IEEE802154_ADDR_LONG; 694 + memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); 193 695 194 - /* request acknowledgment */ 195 - mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; 196 - } 197 - 198 - return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, 199 - type, (void *)&da, (void *)&sa, skb->len); 696 + /* request acknowledgment */ 697 + mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; 200 698 } 699 + 700 + return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, 701 + type, (void *)&da, (void *)&sa, skb->len); 201 702 } 202 703 203 - static int lowpan_give_skb_to_devices(struct sk_buff *skb) 704 + static int lowpan_give_skb_to_devices(struct sk_buff *skb, 705 + struct net_device *dev) 204 706 { 205 707 struct lowpan_dev_record *entry; 206 708 struct sk_buff *skb_cp; ··· 218 722 stat = netif_rx(skb_cp); 219 723 } 220 724 rcu_read_unlock(); 221 - 222 - return stat; 223 - } 224 - 225 - static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr) 226 - { 227 - struct sk_buff *new; 228 - int stat = NET_RX_SUCCESS; 229 - 230 - new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), 231 - GFP_ATOMIC); 232 - kfree_skb(skb); 233 - 234 - if (!new) 235 - return -ENOMEM; 236 - 237 - skb_push(new, sizeof(struct ipv6hdr)); 238 - skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr)); 239 - 240 - new->protocol = htons(ETH_P_IPV6); 241 - new->pkt_type = PACKET_HOST; 242 - 243 - stat = lowpan_give_skb_to_devices(new); 244 - 245 - kfree_skb(new); 246 725 247 726 return stat; 248 727 } ··· 285 814 return NULL; 286 815 } 287 816 288 - static int 289 - lowpan_process_data(struct sk_buff *skb) 817 + static int process_data(struct sk_buff *skb) 290 818 { 291 - struct ipv6hdr hdr = {}; 292 - u8 tmp, iphc0, iphc1, num_context = 0; 819 + u8 iphc0, iphc1; 293 820 const struct ieee802154_addr *_saddr, *_daddr; 294 - int err; 295 821 296 822 lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data, 297 823 skb->len); ··· 393 925 _saddr = &mac_cb(skb)->sa; 394 926 _daddr = &mac_cb(skb)->da; 395 927 396 - pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1); 397 - 398 - /* another if the CID flag is set */ 399 - if (iphc1 & LOWPAN_IPHC_CID) { 400 - pr_debug("CID flag is set, increase header with one\n"); 401 - if (lowpan_fetch_skb_u8(skb, &num_context)) 402 - goto drop; 403 - } 404 - 405 - hdr.version = 6; 406 - 407 - /* Traffic Class and Flow Label */ 408 - switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { 409 - /* 410 - * Traffic Class and FLow Label carried in-line 411 - * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) 412 - */ 413 - case 0: /* 00b */ 414 - if (lowpan_fetch_skb_u8(skb, &tmp)) 415 - goto drop; 416 - 417 - memcpy(&hdr.flow_lbl, &skb->data[0], 3); 418 - skb_pull(skb, 3); 419 - hdr.priority = ((tmp >> 2) & 0x0f); 420 - hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | 421 - (hdr.flow_lbl[0] & 0x0f); 422 - break; 423 - /* 424 - * Traffic class carried in-line 425 - * ECN + DSCP (1 byte), Flow Label is elided 426 - */ 427 - case 2: /* 10b */ 428 - if (lowpan_fetch_skb_u8(skb, &tmp)) 429 - goto drop; 430 - 431 - hdr.priority = ((tmp >> 2) & 0x0f); 432 - hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); 433 - break; 434 - /* 435 - * Flow Label carried in-line 436 - * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided 437 - */ 438 - case 1: /* 01b */ 439 - if (lowpan_fetch_skb_u8(skb, &tmp)) 440 - goto drop; 441 - 442 - hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); 443 - memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); 444 - skb_pull(skb, 2); 445 - break; 446 - /* Traffic Class and Flow Label are elided */ 447 - case 3: /* 11b */ 448 - break; 449 - default: 450 - break; 451 - } 452 - 453 - /* Next Header */ 454 - if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 455 - /* Next header is carried inline */ 456 - if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) 457 - goto drop; 458 - 459 - pr_debug("NH flag is set, next header carried inline: %02x\n", 460 - hdr.nexthdr); 461 - } 462 - 463 - /* Hop Limit */ 464 - if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) 465 - hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; 466 - else { 467 - if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) 468 - goto drop; 469 - } 470 - 471 - /* Extract SAM to the tmp variable */ 472 - tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; 473 - 474 - if (iphc1 & LOWPAN_IPHC_SAC) { 475 - /* Source address context based uncompression */ 476 - pr_debug("SAC bit is set. Handle context based source address.\n"); 477 - err = lowpan_uncompress_context_based_src_addr( 478 - skb, &hdr.saddr, tmp); 479 - } else { 480 - /* Source address uncompression */ 481 - pr_debug("source address stateless compression\n"); 482 - err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr); 483 - } 484 - 485 - /* Check on error of previous branch */ 486 - if (err) 487 - goto drop; 488 - 489 - /* Extract DAM to the tmp variable */ 490 - tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; 491 - 492 - /* check for Multicast Compression */ 493 - if (iphc1 & LOWPAN_IPHC_M) { 494 - if (iphc1 & LOWPAN_IPHC_DAC) { 495 - pr_debug("dest: context-based mcast compression\n"); 496 - /* TODO: implement this */ 497 - } else { 498 - err = lowpan_uncompress_multicast_daddr( 499 - skb, &hdr.daddr, tmp); 500 - if (err) 501 - goto drop; 502 - } 503 - } else { 504 - pr_debug("dest: stateless compression\n"); 505 - err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr); 506 - if (err) 507 - goto drop; 508 - } 509 - 510 - /* UDP data uncompression */ 511 - if (iphc0 & LOWPAN_IPHC_NH_C) { 512 - struct udphdr uh; 513 - struct sk_buff *new; 514 - if (lowpan_uncompress_udp_header(skb, &uh)) 515 - goto drop; 516 - 517 - /* 518 - * replace the compressed UDP head by the uncompressed UDP 519 - * header 520 - */ 521 - new = skb_copy_expand(skb, sizeof(struct udphdr), 522 - skb_tailroom(skb), GFP_ATOMIC); 523 - kfree_skb(skb); 524 - 525 - if (!new) 526 - return -ENOMEM; 527 - 528 - skb = new; 529 - 530 - skb_push(skb, sizeof(struct udphdr)); 531 - skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); 532 - 533 - lowpan_raw_dump_table(__func__, "raw UDP header dump", 534 - (u8 *)&uh, sizeof(uh)); 535 - 536 - hdr.nexthdr = UIP_PROTO_UDP; 537 - } 538 - 539 - /* Not fragmented package */ 540 - hdr.payload_len = htons(skb->len); 541 - 542 - pr_debug("skb headroom size = %d, data length = %d\n", 543 - skb_headroom(skb), skb->len); 544 - 545 - pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" 546 - "nexthdr = 0x%02x\n\thop_lim = %d\n", hdr.version, 547 - ntohs(hdr.payload_len), hdr.nexthdr, hdr.hop_limit); 548 - 549 - lowpan_raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, 550 - sizeof(hdr)); 551 - return lowpan_skb_deliver(skb, &hdr); 928 + return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr, 929 + _saddr->addr_type, IEEE802154_ADDR_LEN, 930 + (u8 *)_daddr->hwaddr, _daddr->addr_type, 931 + IEEE802154_ADDR_LEN, iphc0, iphc1, 932 + lowpan_give_skb_to_devices); 552 933 553 934 unlock_and_drop: 554 935 spin_unlock_bh(&flist_lock); ··· 633 1316 /* Pull off the 1-byte of 6lowpan header. */ 634 1317 skb_pull(local_skb, 1); 635 1318 636 - lowpan_give_skb_to_devices(local_skb); 1319 + lowpan_give_skb_to_devices(local_skb, NULL); 637 1320 638 1321 kfree_skb(local_skb); 639 1322 kfree_skb(skb); ··· 645 1328 local_skb = skb_clone(skb, GFP_ATOMIC); 646 1329 if (!local_skb) 647 1330 goto drop; 648 - lowpan_process_data(local_skb); 1331 + process_data(local_skb); 649 1332 650 1333 kfree_skb(skb); 651 1334 break;
+32
net/ieee802154/6lowpan.h
··· 232 232 dest = 16 bit inline */ 233 233 #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */ 234 234 235 + static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) 236 + { 237 + if (unlikely(!pskb_may_pull(skb, 1))) 238 + return -EINVAL; 239 + 240 + *val = skb->data[0]; 241 + skb_pull(skb, 1); 242 + 243 + return 0; 244 + } 245 + 246 + static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val) 247 + { 248 + if (unlikely(!pskb_may_pull(skb, 2))) 249 + return -EINVAL; 250 + 251 + *val = (skb->data[0] << 8) | skb->data[1]; 252 + skb_pull(skb, 2); 253 + 254 + return 0; 255 + } 256 + 235 257 static inline bool lowpan_fetch_skb(struct sk_buff *skb, 236 258 void *data, const unsigned int len) 237 259 { ··· 265 243 266 244 return false; 267 245 } 246 + 247 + typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev); 248 + 249 + int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, 250 + const u8 *saddr, const u8 saddr_type, const u8 saddr_len, 251 + const u8 *daddr, const u8 daddr_type, const u8 daddr_len, 252 + u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver); 253 + int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 254 + unsigned short type, const void *_daddr, 255 + const void *_saddr, unsigned int len); 268 256 269 257 #endif /* __6LOWPAN_H__ */
+807
net/ieee802154/6lowpan_iphc.c
··· 1 + /* 2 + * Copyright 2011, Siemens AG 3 + * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 4 + */ 5 + 6 + /* 7 + * Based on patches from Jon Smirl <jonsmirl@gmail.com> 8 + * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 12 + * as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License along 20 + * with this program; if not, write to the Free Software Foundation, Inc., 21 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 + */ 23 + 24 + /* Jon's code is based on 6lowpan implementation for Contiki which is: 25 + * Copyright (c) 2008, Swedish Institute of Computer Science. 26 + * All rights reserved. 27 + * 28 + * Redistribution and use in source and binary forms, with or without 29 + * modification, are permitted provided that the following conditions 30 + * are met: 31 + * 1. Redistributions of source code must retain the above copyright 32 + * notice, this list of conditions and the following disclaimer. 33 + * 2. Redistributions in binary form must reproduce the above copyright 34 + * notice, this list of conditions and the following disclaimer in the 35 + * documentation and/or other materials provided with the distribution. 36 + * 3. Neither the name of the Institute nor the names of its contributors 37 + * may be used to endorse or promote products derived from this software 38 + * without specific prior written permission. 39 + * 40 + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 41 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 44 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 + * SUCH DAMAGE. 51 + */ 52 + 53 + #include <linux/bitops.h> 54 + #include <linux/if_arp.h> 55 + #include <linux/netdevice.h> 56 + #include <net/ipv6.h> 57 + #include <net/af_ieee802154.h> 58 + 59 + #include "6lowpan.h" 60 + 61 + /* print data in line */ 62 + static inline void raw_dump_inline(const char *caller, char *msg, 63 + unsigned char *buf, int len) 64 + { 65 + if (msg) 66 + pr_debug("%s():%s: ", caller, msg); 67 + print_hex_dump_debug("", DUMP_PREFIX_NONE, 68 + 16, 1, buf, len, false); 69 + } 70 + 71 + /* 72 + * print data in a table format: 73 + * 74 + * addr: xx xx xx xx xx xx 75 + * addr: xx xx xx xx xx xx 76 + * ... 77 + */ 78 + static inline void raw_dump_table(const char *caller, char *msg, 79 + unsigned char *buf, int len) 80 + { 81 + if (msg) 82 + pr_debug("%s():%s:\n", caller, msg); 83 + print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 84 + 16, 1, buf, len, false); 85 + } 86 + 87 + /* 88 + * Uncompress address function for source and 89 + * destination address(non-multicast). 90 + * 91 + * address_mode is sam value or dam value. 92 + */ 93 + static int uncompress_addr(struct sk_buff *skb, 94 + struct in6_addr *ipaddr, const u8 address_mode, 95 + const u8 *lladdr, const u8 addr_type, 96 + const u8 addr_len) 97 + { 98 + bool fail; 99 + 100 + switch (address_mode) { 101 + case LOWPAN_IPHC_ADDR_00: 102 + /* for global link addresses */ 103 + fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 104 + break; 105 + case LOWPAN_IPHC_ADDR_01: 106 + /* fe:80::XXXX:XXXX:XXXX:XXXX */ 107 + ipaddr->s6_addr[0] = 0xFE; 108 + ipaddr->s6_addr[1] = 0x80; 109 + fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); 110 + break; 111 + case LOWPAN_IPHC_ADDR_02: 112 + /* fe:80::ff:fe00:XXXX */ 113 + ipaddr->s6_addr[0] = 0xFE; 114 + ipaddr->s6_addr[1] = 0x80; 115 + ipaddr->s6_addr[11] = 0xFF; 116 + ipaddr->s6_addr[12] = 0xFE; 117 + fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); 118 + break; 119 + case LOWPAN_IPHC_ADDR_03: 120 + fail = false; 121 + switch (addr_type) { 122 + case IEEE802154_ADDR_LONG: 123 + /* fe:80::XXXX:XXXX:XXXX:XXXX 124 + * \_________________/ 125 + * hwaddr 126 + */ 127 + ipaddr->s6_addr[0] = 0xFE; 128 + ipaddr->s6_addr[1] = 0x80; 129 + memcpy(&ipaddr->s6_addr[8], lladdr, addr_len); 130 + /* second bit-flip (Universe/Local) 131 + * is done according RFC2464 132 + */ 133 + ipaddr->s6_addr[8] ^= 0x02; 134 + break; 135 + case IEEE802154_ADDR_SHORT: 136 + /* fe:80::ff:fe00:XXXX 137 + * \__/ 138 + * short_addr 139 + * 140 + * Universe/Local bit is zero. 141 + */ 142 + ipaddr->s6_addr[0] = 0xFE; 143 + ipaddr->s6_addr[1] = 0x80; 144 + ipaddr->s6_addr[11] = 0xFF; 145 + ipaddr->s6_addr[12] = 0xFE; 146 + ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr)); 147 + break; 148 + default: 149 + pr_debug("Invalid addr_type set\n"); 150 + return -EINVAL; 151 + } 152 + break; 153 + default: 154 + pr_debug("Invalid address mode value: 0x%x\n", address_mode); 155 + return -EINVAL; 156 + } 157 + 158 + if (fail) { 159 + pr_debug("Failed to fetch skb data\n"); 160 + return -EIO; 161 + } 162 + 163 + raw_dump_inline(NULL, "Reconstructed ipv6 addr is", 164 + ipaddr->s6_addr, 16); 165 + 166 + return 0; 167 + } 168 + 169 + /* 170 + * Uncompress address function for source context 171 + * based address(non-multicast). 172 + */ 173 + static int uncompress_context_based_src_addr(struct sk_buff *skb, 174 + struct in6_addr *ipaddr, 175 + const u8 sam) 176 + { 177 + switch (sam) { 178 + case LOWPAN_IPHC_ADDR_00: 179 + /* unspec address :: 180 + * Do nothing, address is already :: 181 + */ 182 + break; 183 + case LOWPAN_IPHC_ADDR_01: 184 + /* TODO */ 185 + case LOWPAN_IPHC_ADDR_02: 186 + /* TODO */ 187 + case LOWPAN_IPHC_ADDR_03: 188 + /* TODO */ 189 + netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); 190 + return -EINVAL; 191 + default: 192 + pr_debug("Invalid sam value: 0x%x\n", sam); 193 + return -EINVAL; 194 + } 195 + 196 + raw_dump_inline(NULL, 197 + "Reconstructed context based ipv6 src addr is", 198 + ipaddr->s6_addr, 16); 199 + 200 + return 0; 201 + } 202 + 203 + static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, 204 + struct net_device *dev, skb_delivery_cb deliver_skb) 205 + { 206 + struct sk_buff *new; 207 + int stat; 208 + 209 + new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), 210 + GFP_ATOMIC); 211 + kfree_skb(skb); 212 + 213 + if (!new) 214 + return -ENOMEM; 215 + 216 + skb_push(new, sizeof(struct ipv6hdr)); 217 + skb_reset_network_header(new); 218 + skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr)); 219 + 220 + new->protocol = htons(ETH_P_IPV6); 221 + new->pkt_type = PACKET_HOST; 222 + new->dev = dev; 223 + 224 + raw_dump_table(__func__, "raw skb data dump before receiving", 225 + new->data, new->len); 226 + 227 + stat = deliver_skb(new, dev); 228 + 229 + kfree_skb(new); 230 + 231 + return stat; 232 + } 233 + 234 + /* Uncompress function for multicast destination address, 235 + * when M bit is set. 236 + */ 237 + static int 238 + lowpan_uncompress_multicast_daddr(struct sk_buff *skb, 239 + struct in6_addr *ipaddr, 240 + const u8 dam) 241 + { 242 + bool fail; 243 + 244 + switch (dam) { 245 + case LOWPAN_IPHC_DAM_00: 246 + /* 00: 128 bits. The full address 247 + * is carried in-line. 248 + */ 249 + fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 250 + break; 251 + case LOWPAN_IPHC_DAM_01: 252 + /* 01: 48 bits. The address takes 253 + * the form ffXX::00XX:XXXX:XXXX. 254 + */ 255 + ipaddr->s6_addr[0] = 0xFF; 256 + fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 257 + fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); 258 + break; 259 + case LOWPAN_IPHC_DAM_10: 260 + /* 10: 32 bits. The address takes 261 + * the form ffXX::00XX:XXXX. 262 + */ 263 + ipaddr->s6_addr[0] = 0xFF; 264 + fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 265 + fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); 266 + break; 267 + case LOWPAN_IPHC_DAM_11: 268 + /* 11: 8 bits. The address takes 269 + * the form ff02::00XX. 270 + */ 271 + ipaddr->s6_addr[0] = 0xFF; 272 + ipaddr->s6_addr[1] = 0x02; 273 + fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); 274 + break; 275 + default: 276 + pr_debug("DAM value has a wrong value: 0x%x\n", dam); 277 + return -EINVAL; 278 + } 279 + 280 + if (fail) { 281 + pr_debug("Failed to fetch skb data\n"); 282 + return -EIO; 283 + } 284 + 285 + raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", 286 + ipaddr->s6_addr, 16); 287 + 288 + return 0; 289 + } 290 + 291 + static int 292 + uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) 293 + { 294 + u8 tmp; 295 + 296 + if (!uh) 297 + goto err; 298 + 299 + if (lowpan_fetch_skb_u8(skb, &tmp)) 300 + goto err; 301 + 302 + if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { 303 + pr_debug("UDP header uncompression\n"); 304 + switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { 305 + case LOWPAN_NHC_UDP_CS_P_00: 306 + memcpy(&uh->source, &skb->data[0], 2); 307 + memcpy(&uh->dest, &skb->data[2], 2); 308 + skb_pull(skb, 4); 309 + break; 310 + case LOWPAN_NHC_UDP_CS_P_01: 311 + memcpy(&uh->source, &skb->data[0], 2); 312 + uh->dest = 313 + skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT; 314 + skb_pull(skb, 3); 315 + break; 316 + case LOWPAN_NHC_UDP_CS_P_10: 317 + uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT; 318 + memcpy(&uh->dest, &skb->data[1], 2); 319 + skb_pull(skb, 3); 320 + break; 321 + case LOWPAN_NHC_UDP_CS_P_11: 322 + uh->source = 323 + LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4); 324 + uh->dest = 325 + LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f); 326 + skb_pull(skb, 1); 327 + break; 328 + default: 329 + pr_debug("ERROR: unknown UDP format\n"); 330 + goto err; 331 + break; 332 + } 333 + 334 + pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", 335 + uh->source, uh->dest); 336 + 337 + /* copy checksum */ 338 + memcpy(&uh->check, &skb->data[0], 2); 339 + skb_pull(skb, 2); 340 + 341 + /* 342 + * UDP lenght needs to be infered from the lower layers 343 + * here, we obtain the hint from the remaining size of the 344 + * frame 345 + */ 346 + uh->len = htons(skb->len + sizeof(struct udphdr)); 347 + pr_debug("uncompressed UDP length: src = %d", uh->len); 348 + } else { 349 + pr_debug("ERROR: unsupported NH format\n"); 350 + goto err; 351 + } 352 + 353 + return 0; 354 + err: 355 + return -EINVAL; 356 + } 357 + 358 + /* TTL uncompression values */ 359 + static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; 360 + 361 + int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, 362 + const u8 *saddr, const u8 saddr_type, const u8 saddr_len, 363 + const u8 *daddr, const u8 daddr_type, const u8 daddr_len, 364 + u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) 365 + { 366 + struct ipv6hdr hdr = {}; 367 + u8 tmp, num_context = 0; 368 + int err; 369 + 370 + raw_dump_table(__func__, "raw skb data dump uncompressed", 371 + skb->data, skb->len); 372 + 373 + /* another if the CID flag is set */ 374 + if (iphc1 & LOWPAN_IPHC_CID) { 375 + pr_debug("CID flag is set, increase header with one\n"); 376 + if (lowpan_fetch_skb_u8(skb, &num_context)) 377 + goto drop; 378 + } 379 + 380 + hdr.version = 6; 381 + 382 + /* Traffic Class and Flow Label */ 383 + switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { 384 + /* 385 + * Traffic Class and FLow Label carried in-line 386 + * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) 387 + */ 388 + case 0: /* 00b */ 389 + if (lowpan_fetch_skb_u8(skb, &tmp)) 390 + goto drop; 391 + 392 + memcpy(&hdr.flow_lbl, &skb->data[0], 3); 393 + skb_pull(skb, 3); 394 + hdr.priority = ((tmp >> 2) & 0x0f); 395 + hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | 396 + (hdr.flow_lbl[0] & 0x0f); 397 + break; 398 + /* 399 + * Traffic class carried in-line 400 + * ECN + DSCP (1 byte), Flow Label is elided 401 + */ 402 + case 2: /* 10b */ 403 + if (lowpan_fetch_skb_u8(skb, &tmp)) 404 + goto drop; 405 + 406 + hdr.priority = ((tmp >> 2) & 0x0f); 407 + hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); 408 + break; 409 + /* 410 + * Flow Label carried in-line 411 + * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided 412 + */ 413 + case 1: /* 01b */ 414 + if (lowpan_fetch_skb_u8(skb, &tmp)) 415 + goto drop; 416 + 417 + hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); 418 + memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); 419 + skb_pull(skb, 2); 420 + break; 421 + /* Traffic Class and Flow Label are elided */ 422 + case 3: /* 11b */ 423 + break; 424 + default: 425 + break; 426 + } 427 + 428 + /* Next Header */ 429 + if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 430 + /* Next header is carried inline */ 431 + if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) 432 + goto drop; 433 + 434 + pr_debug("NH flag is set, next header carried inline: %02x\n", 435 + hdr.nexthdr); 436 + } 437 + 438 + /* Hop Limit */ 439 + if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) 440 + hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; 441 + else { 442 + if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) 443 + goto drop; 444 + } 445 + 446 + /* Extract SAM to the tmp variable */ 447 + tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; 448 + 449 + if (iphc1 & LOWPAN_IPHC_SAC) { 450 + /* Source address context based uncompression */ 451 + pr_debug("SAC bit is set. Handle context based source address.\n"); 452 + err = uncompress_context_based_src_addr( 453 + skb, &hdr.saddr, tmp); 454 + } else { 455 + /* Source address uncompression */ 456 + pr_debug("source address stateless compression\n"); 457 + err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, 458 + saddr_type, saddr_len); 459 + } 460 + 461 + /* Check on error of previous branch */ 462 + if (err) 463 + goto drop; 464 + 465 + /* Extract DAM to the tmp variable */ 466 + tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; 467 + 468 + /* check for Multicast Compression */ 469 + if (iphc1 & LOWPAN_IPHC_M) { 470 + if (iphc1 & LOWPAN_IPHC_DAC) { 471 + pr_debug("dest: context-based mcast compression\n"); 472 + /* TODO: implement this */ 473 + } else { 474 + err = lowpan_uncompress_multicast_daddr( 475 + skb, &hdr.daddr, tmp); 476 + if (err) 477 + goto drop; 478 + } 479 + } else { 480 + err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, 481 + daddr_type, daddr_len); 482 + pr_debug("dest: stateless compression mode %d dest %pI6c\n", 483 + tmp, &hdr.daddr); 484 + if (err) 485 + goto drop; 486 + } 487 + 488 + /* UDP data uncompression */ 489 + if (iphc0 & LOWPAN_IPHC_NH_C) { 490 + struct udphdr uh; 491 + struct sk_buff *new; 492 + if (uncompress_udp_header(skb, &uh)) 493 + goto drop; 494 + 495 + /* 496 + * replace the compressed UDP head by the uncompressed UDP 497 + * header 498 + */ 499 + new = skb_copy_expand(skb, sizeof(struct udphdr), 500 + skb_tailroom(skb), GFP_ATOMIC); 501 + kfree_skb(skb); 502 + 503 + if (!new) 504 + return -ENOMEM; 505 + 506 + skb = new; 507 + 508 + skb_push(skb, sizeof(struct udphdr)); 509 + skb_reset_transport_header(skb); 510 + skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); 511 + 512 + raw_dump_table(__func__, "raw UDP header dump", 513 + (u8 *)&uh, sizeof(uh)); 514 + 515 + hdr.nexthdr = UIP_PROTO_UDP; 516 + } 517 + 518 + hdr.payload_len = htons(skb->len); 519 + 520 + pr_debug("skb headroom size = %d, data length = %d\n", 521 + skb_headroom(skb), skb->len); 522 + 523 + pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" 524 + "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 525 + hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, 526 + hdr.hop_limit, &hdr.daddr); 527 + 528 + raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, 529 + sizeof(hdr)); 530 + 531 + return skb_deliver(skb, &hdr, dev, deliver_skb); 532 + 533 + drop: 534 + kfree_skb(skb); 535 + return -EINVAL; 536 + } 537 + EXPORT_SYMBOL_GPL(lowpan_process_data); 538 + 539 + static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, 540 + const struct in6_addr *ipaddr, 541 + const unsigned char *lladdr) 542 + { 543 + u8 val = 0; 544 + 545 + if (is_addr_mac_addr_based(ipaddr, lladdr)) { 546 + val = 3; /* 0-bits */ 547 + pr_debug("address compression 0 bits\n"); 548 + } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 549 + /* compress IID to 16 bits xxxx::XXXX */ 550 + memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); 551 + *hc06_ptr += 2; 552 + val = 2; /* 16-bits */ 553 + raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", 554 + *hc06_ptr - 2, 2); 555 + } else { 556 + /* do not compress IID => xxxx::IID */ 557 + memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); 558 + *hc06_ptr += 8; 559 + val = 1; /* 64-bits */ 560 + raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", 561 + *hc06_ptr - 8, 8); 562 + } 563 + 564 + return rol8(val, shift); 565 + } 566 + 567 + static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) 568 + { 569 + struct udphdr *uh = udp_hdr(skb); 570 + 571 + if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) == 572 + LOWPAN_NHC_UDP_4BIT_PORT) && 573 + ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) == 574 + LOWPAN_NHC_UDP_4BIT_PORT)) { 575 + pr_debug("UDP header: both ports compression to 4 bits\n"); 576 + **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11; 577 + **(hc06_ptr + 1) = /* subtraction is faster */ 578 + (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) + 579 + ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4)); 580 + *hc06_ptr += 2; 581 + } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) == 582 + LOWPAN_NHC_UDP_8BIT_PORT) { 583 + pr_debug("UDP header: remove 8 bits of dest\n"); 584 + **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01; 585 + memcpy(*hc06_ptr + 1, &uh->source, 2); 586 + **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT); 587 + *hc06_ptr += 4; 588 + } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) == 589 + LOWPAN_NHC_UDP_8BIT_PORT) { 590 + pr_debug("UDP header: remove 8 bits of source\n"); 591 + **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10; 592 + memcpy(*hc06_ptr + 1, &uh->dest, 2); 593 + **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT); 594 + *hc06_ptr += 4; 595 + } else { 596 + pr_debug("UDP header: can't compress\n"); 597 + **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00; 598 + memcpy(*hc06_ptr + 1, &uh->source, 2); 599 + memcpy(*hc06_ptr + 3, &uh->dest, 2); 600 + *hc06_ptr += 5; 601 + } 602 + 603 + /* checksum is always inline */ 604 + memcpy(*hc06_ptr, &uh->check, 2); 605 + *hc06_ptr += 2; 606 + 607 + /* skip the UDP header */ 608 + skb_pull(skb, sizeof(struct udphdr)); 609 + } 610 + 611 + int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 612 + unsigned short type, const void *_daddr, 613 + const void *_saddr, unsigned int len) 614 + { 615 + u8 tmp, iphc0, iphc1, *hc06_ptr; 616 + struct ipv6hdr *hdr; 617 + u8 head[100] = {}; 618 + 619 + if (type != ETH_P_IPV6) 620 + return -EINVAL; 621 + 622 + hdr = ipv6_hdr(skb); 623 + hc06_ptr = head + 2; 624 + 625 + pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 626 + "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 627 + hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, 628 + hdr->hop_limit, &hdr->daddr); 629 + 630 + raw_dump_table(__func__, "raw skb network header dump", 631 + skb_network_header(skb), sizeof(struct ipv6hdr)); 632 + 633 + /* 634 + * As we copy some bit-length fields, in the IPHC encoding bytes, 635 + * we sometimes use |= 636 + * If the field is 0, and the current bit value in memory is 1, 637 + * this does not work. We therefore reset the IPHC encoding here 638 + */ 639 + iphc0 = LOWPAN_DISPATCH_IPHC; 640 + iphc1 = 0; 641 + 642 + /* TODO: context lookup */ 643 + 644 + raw_dump_inline(__func__, "saddr", 645 + (unsigned char *)_saddr, IEEE802154_ADDR_LEN); 646 + raw_dump_inline(__func__, "daddr", 647 + (unsigned char *)_daddr, IEEE802154_ADDR_LEN); 648 + 649 + raw_dump_table(__func__, 650 + "sending raw skb network uncompressed packet", 651 + skb->data, skb->len); 652 + 653 + /* 654 + * Traffic class, flow label 655 + * If flow label is 0, compress it. If traffic class is 0, compress it 656 + * We have to process both in the same time as the offset of traffic 657 + * class depends on the presence of version and flow label 658 + */ 659 + 660 + /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ 661 + tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 662 + tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 663 + 664 + if (((hdr->flow_lbl[0] & 0x0F) == 0) && 665 + (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { 666 + /* flow label can be compressed */ 667 + iphc0 |= LOWPAN_IPHC_FL_C; 668 + if ((hdr->priority == 0) && 669 + ((hdr->flow_lbl[0] & 0xF0) == 0)) { 670 + /* compress (elide) all */ 671 + iphc0 |= LOWPAN_IPHC_TC_C; 672 + } else { 673 + /* compress only the flow label */ 674 + *hc06_ptr = tmp; 675 + hc06_ptr += 1; 676 + } 677 + } else { 678 + /* Flow label cannot be compressed */ 679 + if ((hdr->priority == 0) && 680 + ((hdr->flow_lbl[0] & 0xF0) == 0)) { 681 + /* compress only traffic class */ 682 + iphc0 |= LOWPAN_IPHC_TC_C; 683 + *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 684 + memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); 685 + hc06_ptr += 3; 686 + } else { 687 + /* compress nothing */ 688 + memcpy(hc06_ptr, &hdr, 4); 689 + /* replace the top byte with new ECN | DSCP format */ 690 + *hc06_ptr = tmp; 691 + hc06_ptr += 4; 692 + } 693 + } 694 + 695 + /* NOTE: payload length is always compressed */ 696 + 697 + /* Next Header is compress if UDP */ 698 + if (hdr->nexthdr == UIP_PROTO_UDP) 699 + iphc0 |= LOWPAN_IPHC_NH_C; 700 + 701 + if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 702 + *hc06_ptr = hdr->nexthdr; 703 + hc06_ptr += 1; 704 + } 705 + 706 + /* 707 + * Hop limit 708 + * if 1: compress, encoding is 01 709 + * if 64: compress, encoding is 10 710 + * if 255: compress, encoding is 11 711 + * else do not compress 712 + */ 713 + switch (hdr->hop_limit) { 714 + case 1: 715 + iphc0 |= LOWPAN_IPHC_TTL_1; 716 + break; 717 + case 64: 718 + iphc0 |= LOWPAN_IPHC_TTL_64; 719 + break; 720 + case 255: 721 + iphc0 |= LOWPAN_IPHC_TTL_255; 722 + break; 723 + default: 724 + *hc06_ptr = hdr->hop_limit; 725 + hc06_ptr += 1; 726 + break; 727 + } 728 + 729 + /* source address compression */ 730 + if (is_addr_unspecified(&hdr->saddr)) { 731 + pr_debug("source address is unspecified, setting SAC\n"); 732 + iphc1 |= LOWPAN_IPHC_SAC; 733 + /* TODO: context lookup */ 734 + } else if (is_addr_link_local(&hdr->saddr)) { 735 + iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 736 + LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr); 737 + pr_debug("source address unicast link-local %pI6c " 738 + "iphc1 0x%02x\n", &hdr->saddr, iphc1); 739 + } else { 740 + pr_debug("send the full source address\n"); 741 + memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); 742 + hc06_ptr += 16; 743 + } 744 + 745 + /* destination address compression */ 746 + if (is_addr_mcast(&hdr->daddr)) { 747 + pr_debug("destination address is multicast: "); 748 + iphc1 |= LOWPAN_IPHC_M; 749 + if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 750 + pr_debug("compressed to 1 octet\n"); 751 + iphc1 |= LOWPAN_IPHC_DAM_11; 752 + /* use last byte */ 753 + *hc06_ptr = hdr->daddr.s6_addr[15]; 754 + hc06_ptr += 1; 755 + } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 756 + pr_debug("compressed to 4 octets\n"); 757 + iphc1 |= LOWPAN_IPHC_DAM_10; 758 + /* second byte + the last three */ 759 + *hc06_ptr = hdr->daddr.s6_addr[1]; 760 + memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); 761 + hc06_ptr += 4; 762 + } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 763 + pr_debug("compressed to 6 octets\n"); 764 + iphc1 |= LOWPAN_IPHC_DAM_01; 765 + /* second byte + the last five */ 766 + *hc06_ptr = hdr->daddr.s6_addr[1]; 767 + memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); 768 + hc06_ptr += 6; 769 + } else { 770 + pr_debug("using full address\n"); 771 + iphc1 |= LOWPAN_IPHC_DAM_00; 772 + memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); 773 + hc06_ptr += 16; 774 + } 775 + } else { 776 + /* TODO: context lookup */ 777 + if (is_addr_link_local(&hdr->daddr)) { 778 + iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 779 + LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); 780 + pr_debug("dest address unicast link-local %pI6c " 781 + "iphc1 0x%02x\n", &hdr->daddr, iphc1); 782 + } else { 783 + pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 784 + memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); 785 + hc06_ptr += 16; 786 + } 787 + } 788 + 789 + /* UDP header compression */ 790 + if (hdr->nexthdr == UIP_PROTO_UDP) 791 + compress_udp_header(&hc06_ptr, skb); 792 + 793 + head[0] = iphc0; 794 + head[1] = iphc1; 795 + 796 + skb_pull(skb, sizeof(struct ipv6hdr)); 797 + skb_reset_transport_header(skb); 798 + memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); 799 + skb_reset_network_header(skb); 800 + 801 + pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len); 802 + 803 + raw_dump_table(__func__, "raw skb data dump compressed", 804 + skb->data, skb->len); 805 + return 0; 806 + } 807 + EXPORT_SYMBOL_GPL(lowpan_header_compress);
+1 -1
net/ieee802154/Makefile
··· 1 1 obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o 2 - obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 2 + obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 6lowpan_iphc.o 3 3 4 4 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o 5 5 af_802154-y := af_ieee802154.o raw.o dgram.o