Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
iphc_compress.c
00001 /* 00002 * Copyright (c) 2014-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "nsconfig.h" 00018 #include "ns_list.h" 00019 #include "common_functions.h" 00020 #include "ns_trace.h" 00021 #include "nsdynmemLIB.h" 00022 #include <string.h> 00023 #include "NWK_INTERFACE/Include/protocol.h" 00024 #include "Common_Protocols/ipv6_constants.h" 00025 #include "6LoWPAN/IPHC_Decode/cipv6.h" 00026 00027 #define TRACE_GROUP "iphc" 00028 00029 typedef struct iphc_compress_state { 00030 const lowpan_context_list_t * const context_list; 00031 const uint8_t *in; 00032 uint8_t *out; 00033 uint16_t len; 00034 uint16_t out_space; 00035 uint16_t consumed; 00036 uint16_t produced; 00037 const uint8_t *outer_src_iid; 00038 const uint8_t *outer_dst_iid; 00039 const bool stable_only; 00040 } iphc_compress_state_t; 00041 00042 static bool compress_nh(uint8_t nh, iphc_compress_state_t *restrict cs); 00043 00044 static inline bool context_ok_for_compression(const lowpan_context_t *ctx, bool stable_only) 00045 { 00046 return ctx->lifetime && ctx->compression && (!stable_only || ctx->stable); 00047 } 00048 00049 /* Using a specified context, what's the best possible compression of addr? */ 00050 static uint_fast8_t addr_bytes_needed(const uint8_t *addr, const uint8_t *outer_iid, const uint8_t *ctx_prefix, uint_fast8_t ctx_len) 00051 { 00052 /* Quick test: context always gets priority, so all of context must match */ 00053 /* This handles intrusions into IID space, so don't have to recheck this below */ 00054 if (!bitsequal(addr, ctx_prefix, ctx_len)) { 00055 return 16; 00056 } 00057 00058 /* Okay, potential match, but getting next bit optimal is more complex. */ 00059 /* Try each of 3 possible cases in turn */ 00060 uint8_t template[16]; 00061 00062 /* 0-bit case: 64 bits of IID from outer header */ 00063 /* Template contains 0s, then outer IID, then context on top */ 00064 if (ctx_len < 64) { 00065 memset(template, 0, 8); 00066 } 00067 if (ctx_len < 128) { 00068 memcpy(template + 8, outer_iid, 8); 00069 } 00070 bitcopy(template, ctx_prefix, ctx_len); 00071 00072 if (addr_ipv6_equal(template, addr)) { 00073 return 0; 00074 } 00075 00076 /* 16-bit case: need to match top 14 bytes. Respell top 6 bytes of IID */ 00077 /* from last test to contain 0000:00ff:fe00, unless they're fully */ 00078 /* covered by context, in which case template already hold the correct */ 00079 /* context bytes */ 00080 if (ctx_len < 112) { 00081 memcpy(template + 8, ADDR_SHORT_ADR_SUFFIC, 6); 00082 if (ctx_len > 64) { 00083 bitcopy(template + 8, ctx_prefix + 8, ctx_len - 64); 00084 } 00085 } 00086 if (memcmp(template, addr, 14) == 0) { 00087 return 2; 00088 } 00089 00090 /* 64-bit case: only need to match top 8 bytes */ 00091 if (memcmp(template, addr, 8) == 0) { 00092 return 8; 00093 } 00094 00095 /* Had a matching context, but didn't match enough. Example: 00096 * Context = 2002:db4::/32, Addr = 2002:db4:1::1 00097 * Matches all 32 bits of context length, but not enough to compress 64-bit 00098 */ 00099 return 16; 00100 } 00101 00102 static uint8_t compress_mc_addr(const lowpan_context_list_t *context_list, const uint8_t *addr, uint8_t *cmp_addr_out, uint8_t *context, uint8_t *mode, bool stable_only) 00103 { 00104 *mode |= HC_MULTICAST_COMP; 00105 if (memcmp(addr, ADDR_LINK_LOCAL_ALL_NODES, 15) == 0) { 00106 // ff02:0000:0000:0000:0000:0000:0000:00XX 00107 cmp_addr_out[0] = addr[15]; 00108 *mode |= HC_8BIT_MULTICAST; 00109 return 1; 00110 } 00111 if (memcmp(addr + 2, ADDR_LINK_LOCAL_ALL_NODES + 2, 11) == 0) { 00112 // ffXX:0000:0000:0000:0000:0000:00XX:XXXX 00113 cmp_addr_out[0] = addr[1]; 00114 cmp_addr_out[1] = addr[13]; 00115 cmp_addr_out[2] = addr[14]; 00116 cmp_addr_out[3] = addr[15]; 00117 *mode |= HC_32BIT_MULTICAST; 00118 return 4; 00119 } 00120 if (memcmp(addr + 2, ADDR_LINK_LOCAL_ALL_NODES + 2, 9) == 0) { 00121 // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX 00122 cmp_addr_out[0] = addr[1]; 00123 memcpy(cmp_addr_out + 1, addr + 11, 5); 00124 *mode |= HC_48BIT_MULTICAST; 00125 return 6; 00126 } 00127 /* Looking for addresses of the form ffxx:xxLL:PPPP:PPPP:PPPP:PPPP:xxxx:xxxx */ 00128 /* Context info is padded with zeros, so the 8-byte memcmp is okay for short contexts. */ 00129 /* RFCs are ambiguous about how this should work if prefix length is > 64 bits, */ 00130 /* so don't attempt compression against long contexts. */ 00131 ns_list_foreach(lowpan_context_t, ctx, context_list) { 00132 if (context_ok_for_compression(ctx, stable_only) && 00133 ctx->length <= 64 && 00134 addr[3] == ctx->length && memcmp(addr + 4, ctx->prefix, 8) == 0) { 00135 cmp_addr_out[0] = addr[1]; 00136 cmp_addr_out[1] = addr[2]; 00137 memcpy(cmp_addr_out + 2, addr + 12, 4); 00138 *context |= ctx->cid; 00139 *mode |= HC_48BIT_CONTEXT_MULTICAST; 00140 return 6; 00141 } 00142 } 00143 00144 memcpy(cmp_addr_out, addr, 16); 00145 *mode |= HC_128BIT_MULTICAST; 00146 return 16; 00147 } 00148 00149 static uint8_t compress_addr(const lowpan_context_list_t *context_list, const uint8_t *addr, bool is_dst, const uint8_t *outer_iid, uint8_t *cmp_addr_out, uint8_t *context, uint8_t *mode, bool stable_only) 00150 { 00151 if (is_dst && addr[0] == 0xff) { 00152 return compress_mc_addr(context_list, addr, cmp_addr_out, context, mode, stable_only); 00153 } 00154 00155 uint_fast8_t best_bytes = addr_bytes_needed(addr, outer_iid, ADDR_LINK_LOCAL_PREFIX, 64); 00156 lowpan_context_t *best_ctx = NULL; 00157 bool checked_ctx0 = false; 00158 00159 if (best_bytes > 0) { 00160 ns_list_foreach(lowpan_context_t, ctx, context_list) { 00161 if (!context_ok_for_compression(ctx, stable_only)) { 00162 continue; 00163 } 00164 00165 uint_fast8_t bytes = addr_bytes_needed(addr, outer_iid, ctx->prefix, ctx->length); 00166 if (ctx->cid == 0) { 00167 checked_ctx0 = true; 00168 } 00169 /* This context is better if: 00170 * a) it means fewer inline bytes, or 00171 * b) it needs the same inline bytes and might avoid a CID extension 00172 */ 00173 if (bytes < best_bytes || (bytes == best_bytes && ctx->cid == 0 && best_ctx && best_ctx->cid != 0)) { 00174 best_ctx = ctx; 00175 best_bytes = bytes; 00176 /* Don't need to check further if we've reached 0 bytes, and we've considered context 0 */ 00177 if (best_bytes == 0 && checked_ctx0) { 00178 break; 00179 } 00180 } 00181 } 00182 } 00183 00184 /* If not found a 0-byte match, one more (unlikely) possibility for source - special case for "unspecified" */ 00185 if (best_bytes > 0 && !is_dst && addr_is_ipv6_unspecified(addr)) { 00186 *mode |= HC_SRCADR_COMP | HC_SRC_ADR_128_BIT; 00187 return 0; 00188 } 00189 00190 uint8_t mode_bits; 00191 uint8_t context_bits; 00192 if (best_ctx) { 00193 context_bits = best_ctx->cid; 00194 mode_bits = HC_DSTADR_COMP; 00195 } else { 00196 context_bits = 0; 00197 mode_bits = 0; 00198 } 00199 00200 switch (best_bytes) { 00201 default: 00202 mode_bits |= HC_DST_ADR_128_BIT; 00203 break; 00204 case 8: 00205 mode_bits |= HC_DST_ADR_64_BIT; 00206 break; 00207 case 2: 00208 mode_bits |= HC_DST_ADR_16_BIT; 00209 break; 00210 case 0: 00211 mode_bits |= HC_DST_ADR_FROM_MAC; 00212 break; 00213 } 00214 00215 /* Convert from IPHC DST bits to SRC bits */ 00216 if (!is_dst) { 00217 mode_bits <<= 4; 00218 context_bits <<= 4; 00219 } 00220 00221 *mode |= mode_bits; 00222 *context |= context_bits; 00223 00224 memcpy(cmp_addr_out, addr + (16 - best_bytes), best_bytes); 00225 00226 return best_bytes; 00227 } 00228 00229 static bool compress_udp(iphc_compress_state_t *restrict cs) 00230 { 00231 if (cs->len < 8) { 00232 return false; 00233 } 00234 00235 /* UDP length should be set to payload length - if it's not, we can't compress it */ 00236 uint16_t udp_len = common_read_16_bit(cs->in + 4); 00237 if (udp_len != cs->len) { 00238 return false; 00239 } 00240 00241 uint16_t src_port = common_read_16_bit(cs->in + 0); 00242 uint16_t dst_port = common_read_16_bit(cs->in + 2); 00243 00244 uint8_t *ptr = cs->out; 00245 if ((src_port & 0xfff0) == 0xf0b0 && 00246 (dst_port & 0xfff0) == 0xf0b0) { 00247 if (cs->out_space < 4) { 00248 return false; 00249 } 00250 *ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_BOTH; 00251 *ptr++ = (src_port & 0xF) << 4 | 00252 (dst_port & 0xF); 00253 } else if ((src_port & 0xff00) == 0xf000) { 00254 if (cs->out_space < 7) { 00255 return false; 00256 } 00257 *ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_SRC; 00258 *ptr++ = src_port & 0xff; 00259 ptr = common_write_16_bit(dst_port, ptr); 00260 } else if ((dst_port & 0xff00) == 0xf000) { 00261 if (cs->out_space < 7) { 00262 return false; 00263 } 00264 *ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_DST; 00265 ptr = common_write_16_bit(src_port, ptr); 00266 *ptr++ = dst_port & 0xff; 00267 } else { 00268 if (cs->out_space < 8) { 00269 return false; 00270 } 00271 *ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_NONE; 00272 ptr = common_write_16_bit(src_port, ptr); 00273 ptr = common_write_16_bit(dst_port, ptr); 00274 } 00275 00276 /* Checksum */ 00277 *ptr++ = cs->in[6]; 00278 *ptr++ = cs->in[7]; 00279 uint_fast8_t outlen = ptr - cs->out; 00280 00281 cs->consumed += 8; 00282 cs->in += 8; 00283 cs->len -= 8; 00284 cs->out_space -= outlen; 00285 cs->out += outlen; 00286 cs->produced += outlen; 00287 00288 return true; 00289 } 00290 00291 00292 static bool compress_exthdr(uint8_t nhc, iphc_compress_state_t *restrict cs) 00293 { 00294 if (cs->len < 8) { 00295 return false; 00296 } 00297 00298 const uint8_t *in = cs->in; 00299 uint8_t nh = in[0]; 00300 uint16_t hdrlen; 00301 00302 if (nhc == NHC_EXT_FRAG) { 00303 /* For fragment header, seems sensible to only handle first fragment; 00304 * "Next header" field doesn't describe following data otherwise. 00305 * Could still "compress" this header in all cases, but no point if we don't 00306 * have following headers to compress - it takes 8 bytes either way. 00307 */ 00308 uint16_t offset = common_read_16_bit(in + 2) & 0xFFF8; 00309 if (offset != 0) { 00310 return false; 00311 } 00312 00313 /* Second byte is reserved; it's not a length byte */ 00314 hdrlen = 8; 00315 } else { 00316 hdrlen = (in[1] + 1) * 8; 00317 } 00318 00319 if (hdrlen > cs->len || hdrlen >= 256) { 00320 return false; 00321 } 00322 00323 /* If Options are well-formed, parse and remove final option if it's padding */ 00324 uint8_t hc_bytes = hdrlen; 00325 if (nhc == NHC_EXT_DEST_OPT || nhc == NHC_EXT_HOP_BY_HOP) { 00326 const uint8_t *opt = in + 2, *lastopt = opt; 00327 uint8_t optrem = hdrlen - 2; 00328 00329 while (optrem) { 00330 lastopt = opt; 00331 if (opt[0] == IPV6_OPTION_PAD1) { 00332 opt++; 00333 optrem--; 00334 continue; 00335 } 00336 if (optrem < 2 || optrem < 2 + opt[1]) { 00337 lastopt = NULL; 00338 break; 00339 } 00340 optrem -= 2 + opt[1]; 00341 opt += 2 + opt[1]; 00342 } 00343 if (lastopt && (lastopt[0] == IPV6_OPTION_PAD1 || lastopt[0] == IPV6_OPTION_PADN)) { 00344 hc_bytes = lastopt - in; 00345 } 00346 } 00347 00348 /* Include one for "next header" - we will either need this ourselves, or 00349 * the next hdr will*/ 00350 if (cs->out_space < hc_bytes + 1) { 00351 return false; 00352 } 00353 00354 uint8_t *out = cs->out; 00355 00356 cs->in += hdrlen; 00357 cs->len -= hdrlen; 00358 cs->consumed += hdrlen; 00359 cs->out += hc_bytes; 00360 cs->out_space -= hc_bytes; 00361 cs->produced += hc_bytes; 00362 00363 out[0] = nhc; 00364 if (compress_nh(nh, cs)) { 00365 out[0] |= NHC_EXT_NH; 00366 } 00367 00368 uint8_t *ptr = out + 1; 00369 if (!(out[0] & NHC_EXT_NH)) { 00370 *ptr++ = nh; 00371 cs->out++; 00372 cs->out_space--; 00373 cs->produced++; 00374 } 00375 if (nhc == NHC_EXT_FRAG) { 00376 *ptr++ = in[1]; 00377 } else { 00378 *ptr++ = hc_bytes - 2; 00379 } 00380 memcpy(ptr, in + 2, hc_bytes - 2); 00381 return true; 00382 } 00383 00384 static bool compress_ipv6(iphc_compress_state_t *restrict cs, bool from_nhc) 00385 { 00386 const uint8_t *const in = cs->in; 00387 uint8_t *const out = cs->out; 00388 00389 /* Need at least 2 plus 1 for next header field or following NHC byte */ 00390 /* plus another 1 if coming from NHC (for NHC_EXT_IPV6 byte) */ 00391 if (cs->out_space < from_nhc + 3) { 00392 return false; 00393 } 00394 00395 if (cs->len < 40 || (in[0] & 0xF0) != 0x60) { 00396 tr_debug("Not IPv6"); 00397 return false; 00398 } 00399 uint8_t iphc[2] = { LOWPAN_DISPATCH_IPHC, 0 }; 00400 uint_fast8_t iphc_bytes = from_nhc + 2; 00401 00402 /* Payload length field must match, or we can't compress */ 00403 if (common_read_16_bit(in + 4) != cs->len - 40) { 00404 return false; 00405 } 00406 00407 /* Compress addresses, get context byte */ 00408 uint8_t cid = 0; 00409 uint8_t cmp_src[16], cmp_dst[16], cmp_src_len, cmp_dst_len; 00410 cmp_src_len = compress_addr(cs->context_list, in + 8, false, cs->outer_src_iid, cmp_src, &cid, &iphc[1], cs->stable_only); 00411 cmp_dst_len = compress_addr(cs->context_list, in + 24, true, cs->outer_dst_iid, cmp_dst, &cid, &iphc[1], cs->stable_only); 00412 iphc_bytes += cmp_src_len + cmp_dst_len; 00413 if (cid != 0) { 00414 iphc_bytes += 1; 00415 iphc[1] |= HC_CIDE_COMP; 00416 } 00417 00418 /* Compress Hop Limit */ 00419 switch (cs->in[7]) { 00420 case 255: 00421 iphc[0] |= HC_HOP_LIMIT_255; 00422 break; 00423 case 64: 00424 iphc[0] |= HC_HOP_LIMIT_64; 00425 break; 00426 case 1: 00427 iphc[0] |= HC_HOP_LIMIT_1; 00428 break; 00429 default: 00430 iphc[0] |= HC_HOP_LIMIT_CARRIED_IN_LINE; 00431 iphc_bytes += 1; 00432 break; 00433 } 00434 00435 uint8_t ecn = (in[1] & 0x30) << 2; 00436 uint8_t dscp = (in[0] & 0x0F) << 2 | (in[1] & 0xC0) >> 6; 00437 uint_fast24_t flow = common_read_24_bit(in + 1) & 0xFFFFF; 00438 00439 if (flow == 0 && ecn == 0 && dscp == 0) { 00440 iphc[0] |= HC_TF_ELIDED; 00441 } else if (flow == 0) { 00442 iphc[0] |= HC_TF_ECN_DSCP; 00443 iphc_bytes += 1; 00444 } else if (dscp == 0) { 00445 iphc[0] |= HC_TF_ECN_FLOW_LABEL; 00446 flow |= (uint_fast24_t) ecn << 16; 00447 iphc_bytes += 3; 00448 } else { 00449 iphc[0] |= HC_TF_ECN_DSCP_FLOW_LABEL; 00450 iphc_bytes += 4; 00451 } 00452 00453 /* Include one for "next header" - we will either need this ourselves, or 00454 * the next H will*/ 00455 if (cs->out_space < iphc_bytes + 1) { 00456 return false; 00457 } 00458 00459 /* Update state for next header */ 00460 cs->in += 40; 00461 cs->len -= 40; 00462 cs->consumed += 40; 00463 00464 cs->out += iphc_bytes; 00465 cs->out_space -= iphc_bytes; 00466 cs->produced += iphc_bytes; 00467 00468 cs->outer_src_iid = in + 16; 00469 cs->outer_dst_iid = in + 32; 00470 00471 /* Check if next header can be compressed - potentially recursing */ 00472 if (compress_nh(in[6], cs)) { 00473 iphc[0] |= HC_NEXT_HEADER_MASK; 00474 } else { 00475 /* We produce one more byte for Next Header */ 00476 iphc_bytes++; 00477 cs->out++; 00478 cs->out_space--; 00479 cs->produced++; 00480 } 00481 00482 uint8_t *ptr = out; 00483 if (from_nhc) { 00484 *ptr++ = NHC_EXT_IPV6; 00485 } 00486 *ptr++ = iphc[0]; 00487 *ptr++ = iphc[1]; 00488 if (cid != 0) { 00489 *ptr++ = cid; 00490 } 00491 00492 if ((iphc[0] & HC_TF_MASK) == HC_TF_ECN_DSCP_FLOW_LABEL || (iphc[0] & HC_TF_MASK) == HC_TF_ECN_DSCP) { 00493 *ptr++ = (ecn | dscp); 00494 } 00495 if ((iphc[0] & HC_TF_MASK) == HC_TF_ECN_DSCP_FLOW_LABEL || (iphc[0] & HC_TF_MASK) == HC_TF_ECN_FLOW_LABEL) { 00496 ptr = common_write_24_bit(flow, ptr); // "flow" includes ecn in 3-byte case 00497 } 00498 00499 if (!(iphc[0] & HC_NEXT_HEADER_MASK)) { 00500 *ptr++ = in[6]; 00501 } 00502 00503 if ((iphc[0] & HC_HOP_LIMIT_MASK) == HC_HOP_LIMIT_CARRIED_IN_LINE) { 00504 *ptr++ = in[7]; 00505 } 00506 00507 ptr = (uint8_t *) memcpy(ptr, cmp_src, cmp_src_len) + cmp_src_len; 00508 ptr = (uint8_t *) memcpy(ptr, cmp_dst, cmp_dst_len) + cmp_dst_len; 00509 00510 if (ptr != out + iphc_bytes) { 00511 tr_debug("iphc error"); 00512 } 00513 00514 return true; 00515 } 00516 00517 static bool compress_nh(uint8_t nh, iphc_compress_state_t *restrict cs) 00518 { 00519 switch (nh) { 00520 uint8_t nhc; 00521 case IPV6_NH_HOP_BY_HOP: 00522 nhc = NHC_EXT_HOP_BY_HOP; 00523 goto ext_hdr; 00524 case IPV6_NH_ROUTING: 00525 nhc = NHC_EXT_ROUTING; 00526 goto ext_hdr; 00527 case IPV6_NH_FRAGMENT: 00528 nhc = NHC_EXT_FRAG; 00529 goto ext_hdr; 00530 case IPV6_NH_DEST_OPT: 00531 nhc = NHC_EXT_DEST_OPT; 00532 goto ext_hdr; 00533 case IPV6_NH_MOBILITY: 00534 nhc = NHC_EXT_MOBILITY; 00535 ext_hdr: 00536 return compress_exthdr(nhc, cs); 00537 /* no break */ 00538 case IPV6_NH_IPV6: 00539 return compress_ipv6(cs, true); 00540 case IPV6_NH_UDP: 00541 return compress_udp(cs); 00542 default: 00543 return false; 00544 } 00545 } 00546 00547 00548 /* Input: An IPv6 frame, with outer layer 802.15.4 MAC (or IP) addresses in src+dst */ 00549 /* Output: 6LoWPAN frame - usually compressed. */ 00550 buffer_t *iphc_compress(const lowpan_context_list_t *context_list, buffer_t *buf, uint16_t hc_space, bool stable_only) 00551 { 00552 uint8_t *ptr = buffer_data_pointer(buf); 00553 uint16_t len = buffer_data_length(buf); 00554 uint8_t src_iid[8], dst_iid[8]; 00555 00556 if (len < 40 || (ptr[0] & 0xF0) != 0x60) { 00557 tr_debug("Not IPv6"); 00558 return buffer_free(buf); 00559 } 00560 00561 /* No point allocating excessively */ 00562 if (hc_space > len) { 00563 hc_space = len; 00564 } 00565 00566 /* TODO: Could actually do it in-place with more care, working backwards 00567 * in each header. 00568 */ 00569 uint8_t *hc_out = ns_dyn_mem_temporary_alloc(hc_space); 00570 if (!hc_out) { 00571 tr_debug("No mem"); 00572 return buffer_free(buf); 00573 } 00574 00575 if (!addr_iid_from_outer(src_iid, &buf->src_sa ) || !addr_iid_from_outer(dst_iid, &buf->dst_sa )) { 00576 tr_debug("Bad outer addr"); 00577 ns_dyn_mem_free(hc_out); 00578 return buffer_free(buf); 00579 } 00580 00581 iphc_compress_state_t cs = { 00582 .context_list = context_list, 00583 .in = ptr, 00584 .len = len, 00585 .out = hc_out, 00586 .out_space = hc_space, 00587 .consumed = 0, 00588 .produced = 0, 00589 .outer_src_iid = src_iid, 00590 .outer_dst_iid = dst_iid, 00591 .stable_only = stable_only 00592 }; 00593 00594 if (!compress_ipv6(&cs, false) || cs.produced > cs.consumed) { 00595 /* Compression failed, or made it bigger somehow (impossible?) */ 00596 /* Fall back to uncompressed, which means adding a dispatch byte */ 00597 buf = buffer_headroom(buf, 1); 00598 if (buf) { 00599 ptr = buffer_data_reserve_header(buf, 1); 00600 *ptr = LOWPAN_DISPATCH_IPV6; 00601 } 00602 ns_dyn_mem_free(hc_out); 00603 return buf; 00604 } 00605 00606 buffer_data_strip_header(buf, cs.consumed); 00607 buffer_data_reserve_header(buf, cs.produced); 00608 /* XXX see note above - should be able to improve this to avoid the temp buffer */ 00609 memcpy(buffer_data_pointer(buf), hc_out, cs.produced); 00610 ns_dyn_mem_free(hc_out); 00611 return buf; 00612 00613 }
Generated on Fri Jul 22 2022 04:53:50 by
1.7.2
