mbed client on ethernet with LWIP
Dependencies: mbed Socket lwip-eth lwip-sys lwip
Fork of mbed-client-classic-example-lwip by
nanostack-libservice/source/IPv6_fcf_lib/ip_fsc.c@11:cada08fc8a70, 2016-06-09 (annotated)
- Committer:
- mbedAustin
- Date:
- Thu Jun 09 17:08:36 2016 +0000
- Revision:
- 11:cada08fc8a70
Commit for public Consumption
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbedAustin | 11:cada08fc8a70 | 1 | /* |
mbedAustin | 11:cada08fc8a70 | 2 | * Copyright (c) 2014-2015 ARM Limited. All rights reserved. |
mbedAustin | 11:cada08fc8a70 | 3 | * SPDX-License-Identifier: Apache-2.0 |
mbedAustin | 11:cada08fc8a70 | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
mbedAustin | 11:cada08fc8a70 | 5 | * not use this file except in compliance with the License. |
mbedAustin | 11:cada08fc8a70 | 6 | * You may obtain a copy of the License at |
mbedAustin | 11:cada08fc8a70 | 7 | * |
mbedAustin | 11:cada08fc8a70 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
mbedAustin | 11:cada08fc8a70 | 9 | * |
mbedAustin | 11:cada08fc8a70 | 10 | * Unless required by applicable law or agreed to in writing, software |
mbedAustin | 11:cada08fc8a70 | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
mbedAustin | 11:cada08fc8a70 | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
mbedAustin | 11:cada08fc8a70 | 13 | * See the License for the specific language governing permissions and |
mbedAustin | 11:cada08fc8a70 | 14 | * limitations under the License. |
mbedAustin | 11:cada08fc8a70 | 15 | */ |
mbedAustin | 11:cada08fc8a70 | 16 | #include "stdint.h" |
mbedAustin | 11:cada08fc8a70 | 17 | #include "ip_fsc.h" |
mbedAustin | 11:cada08fc8a70 | 18 | |
mbedAustin | 11:cada08fc8a70 | 19 | /** \brief Compute IP checksum for arbitary data |
mbedAustin | 11:cada08fc8a70 | 20 | * |
mbedAustin | 11:cada08fc8a70 | 21 | * Compute an IP checksum, given a arbitrary gather list. |
mbedAustin | 11:cada08fc8a70 | 22 | * |
mbedAustin | 11:cada08fc8a70 | 23 | * See ipv6_fcf for discussion of use. |
mbedAustin | 11:cada08fc8a70 | 24 | * |
mbedAustin | 11:cada08fc8a70 | 25 | * This will work for any arbitrary gather list - it can handle odd |
mbedAustin | 11:cada08fc8a70 | 26 | * alignments. The one limitation is that the 32-bit accumulator limits |
mbedAustin | 11:cada08fc8a70 | 27 | * it to basically 64K of total data. |
mbedAustin | 11:cada08fc8a70 | 28 | */ |
mbedAustin | 11:cada08fc8a70 | 29 | uint16_t ip_fcf_v(uint_fast8_t count, const ns_iovec_t vec[static count]) |
mbedAustin | 11:cada08fc8a70 | 30 | { |
mbedAustin | 11:cada08fc8a70 | 31 | uint_fast32_t acc32 = 0; |
mbedAustin | 11:cada08fc8a70 | 32 | bool odd = false; |
mbedAustin | 11:cada08fc8a70 | 33 | while (count) { |
mbedAustin | 11:cada08fc8a70 | 34 | const uint8_t *data_ptr = vec->iov_base; |
mbedAustin | 11:cada08fc8a70 | 35 | uint_fast16_t data_length = vec->iov_len; |
mbedAustin | 11:cada08fc8a70 | 36 | if (odd && data_length > 0) { |
mbedAustin | 11:cada08fc8a70 | 37 | acc32 += *data_ptr++; |
mbedAustin | 11:cada08fc8a70 | 38 | data_length--; |
mbedAustin | 11:cada08fc8a70 | 39 | odd = false; |
mbedAustin | 11:cada08fc8a70 | 40 | } |
mbedAustin | 11:cada08fc8a70 | 41 | while (data_length >= 2) { |
mbedAustin | 11:cada08fc8a70 | 42 | acc32 += (uint_fast16_t) data_ptr[0] << 8 | data_ptr[1]; |
mbedAustin | 11:cada08fc8a70 | 43 | data_ptr += 2; |
mbedAustin | 11:cada08fc8a70 | 44 | data_length -= 2; |
mbedAustin | 11:cada08fc8a70 | 45 | } |
mbedAustin | 11:cada08fc8a70 | 46 | if (data_length) { |
mbedAustin | 11:cada08fc8a70 | 47 | acc32 += (uint_fast16_t) data_ptr[0] << 8; |
mbedAustin | 11:cada08fc8a70 | 48 | odd = true; |
mbedAustin | 11:cada08fc8a70 | 49 | } |
mbedAustin | 11:cada08fc8a70 | 50 | vec++; |
mbedAustin | 11:cada08fc8a70 | 51 | count--; |
mbedAustin | 11:cada08fc8a70 | 52 | } |
mbedAustin | 11:cada08fc8a70 | 53 | |
mbedAustin | 11:cada08fc8a70 | 54 | // Fold down up to 0xffff carries in the 32-bit accumulator |
mbedAustin | 11:cada08fc8a70 | 55 | acc32 = (acc32 >> 16) + (acc32 & 0xffff); |
mbedAustin | 11:cada08fc8a70 | 56 | |
mbedAustin | 11:cada08fc8a70 | 57 | // Could be one more carry from the previous addition (result <= 0x1fffe) |
mbedAustin | 11:cada08fc8a70 | 58 | uint16_t sum16 = (uint16_t)((acc32 >> 16) + (acc32 & 0xffff)); |
mbedAustin | 11:cada08fc8a70 | 59 | return ~sum16; |
mbedAustin | 11:cada08fc8a70 | 60 | } |
mbedAustin | 11:cada08fc8a70 | 61 | |
mbedAustin | 11:cada08fc8a70 | 62 | /** \brief Compute IPv6 checksum |
mbedAustin | 11:cada08fc8a70 | 63 | * |
mbedAustin | 11:cada08fc8a70 | 64 | * Compute an IPv6 checksum, given fields of an IPv6 pseudoheader and payload. |
mbedAustin | 11:cada08fc8a70 | 65 | * |
mbedAustin | 11:cada08fc8a70 | 66 | * This returns the 1's-complement of the checksum, as required when |
mbedAustin | 11:cada08fc8a70 | 67 | * generating the checksum for transmission. The result can be 0x0000; |
mbedAustin | 11:cada08fc8a70 | 68 | * for UDP (only) this must be transformed to 0xFFFF to distinguish from |
mbedAustin | 11:cada08fc8a70 | 69 | * a packet with no checksum. |
mbedAustin | 11:cada08fc8a70 | 70 | * |
mbedAustin | 11:cada08fc8a70 | 71 | * To check a packet, this function will return 0 when run on a |
mbedAustin | 11:cada08fc8a70 | 72 | * packet with a valid checksum. Checksums should be checked like this rather |
mbedAustin | 11:cada08fc8a70 | 73 | * than setting the checksum field to zero and comparing generated checksum with |
mbedAustin | 11:cada08fc8a70 | 74 | * the original value - this would fail in the case the received packet had |
mbedAustin | 11:cada08fc8a70 | 75 | * checksum 0xFFFF. |
mbedAustin | 11:cada08fc8a70 | 76 | */ |
mbedAustin | 11:cada08fc8a70 | 77 | uint16_t ipv6_fcf(const uint8_t src_address[static 16], const uint8_t dest_address[static 16], |
mbedAustin | 11:cada08fc8a70 | 78 | uint16_t data_length, const uint8_t data_ptr[static data_length], uint8_t next_protocol) |
mbedAustin | 11:cada08fc8a70 | 79 | { |
mbedAustin | 11:cada08fc8a70 | 80 | // Use gather vector to lay out IPv6 pseudo-header (RFC 2460) and data |
mbedAustin | 11:cada08fc8a70 | 81 | uint8_t hdr_data[] = { data_length >> 8, data_length, 0, next_protocol }; |
mbedAustin | 11:cada08fc8a70 | 82 | ns_iovec_t vec[4] = { |
mbedAustin | 11:cada08fc8a70 | 83 | { (void *) src_address, 16 }, |
mbedAustin | 11:cada08fc8a70 | 84 | { (void *) dest_address, 16 }, |
mbedAustin | 11:cada08fc8a70 | 85 | { hdr_data, 4 }, |
mbedAustin | 11:cada08fc8a70 | 86 | { (void *) data_ptr, data_length } |
mbedAustin | 11:cada08fc8a70 | 87 | }; |
mbedAustin | 11:cada08fc8a70 | 88 | |
mbedAustin | 11:cada08fc8a70 | 89 | return ip_fcf_v(4, vec); |
mbedAustin | 11:cada08fc8a70 | 90 | } |