Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
ip_fsc.c
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "stdint.h" 00017 #include "ip_fsc.h" 00018 00019 /** \brief Compute IP checksum for arbitary data 00020 * 00021 * Compute an IP checksum, given a arbitrary gather list. 00022 * 00023 * See ipv6_fcf for discussion of use. 00024 * 00025 * This will work for any arbitrary gather list - it can handle odd 00026 * alignments. The one limitation is that the 32-bit accumulator limits 00027 * it to basically 64K of total data. 00028 */ 00029 uint16_t ip_fcf_v(uint_fast8_t count, const ns_iovec_t vec[static count]) 00030 { 00031 uint_fast32_t acc32 = 0; 00032 bool odd = false; 00033 while (count) { 00034 const uint8_t *data_ptr = vec->iov_base; 00035 uint_fast16_t data_length = vec->iov_len; 00036 if (odd && data_length > 0) { 00037 acc32 += *data_ptr++; 00038 data_length--; 00039 odd = false; 00040 } 00041 while (data_length >= 2) { 00042 acc32 += (uint_fast16_t) data_ptr[0] << 8 | data_ptr[1]; 00043 data_ptr += 2; 00044 data_length -= 2; 00045 } 00046 if (data_length) { 00047 acc32 += (uint_fast16_t) data_ptr[0] << 8; 00048 odd = true; 00049 } 00050 vec++; 00051 count--; 00052 } 00053 00054 // Fold down up to 0xffff carries in the 32-bit accumulator 00055 acc32 = (acc32 >> 16) + (acc32 & 0xffff); 00056 00057 // Could be one more carry from the previous addition (result <= 0x1fffe) 00058 uint16_t sum16 = (uint16_t)((acc32 >> 16) + (acc32 & 0xffff)); 00059 return ~sum16; 00060 } 00061 00062 /** \brief Compute IPv6 checksum 00063 * 00064 * Compute an IPv6 checksum, given fields of an IPv6 pseudoheader and payload. 00065 * 00066 * This returns the 1's-complement of the checksum, as required when 00067 * generating the checksum for transmission. The result can be 0x0000; 00068 * for UDP (only) this must be transformed to 0xFFFF to distinguish from 00069 * a packet with no checksum. 00070 * 00071 * To check a packet, this function will return 0 when run on a 00072 * packet with a valid checksum. Checksums should be checked like this rather 00073 * than setting the checksum field to zero and comparing generated checksum with 00074 * the original value - this would fail in the case the received packet had 00075 * checksum 0xFFFF. 00076 */ 00077 uint16_t ipv6_fcf(const uint8_t src_address[static 16], const uint8_t dest_address[static 16], 00078 uint16_t data_length, const uint8_t data_ptr[static data_length], uint8_t next_protocol) 00079 { 00080 // Use gather vector to lay out IPv6 pseudo-header (RFC 2460) and data 00081 uint8_t hdr_data[] = { data_length >> 8, data_length, 0, next_protocol }; 00082 ns_iovec_t vec[4] = { 00083 { (void *) src_address, 16 }, 00084 { (void *) dest_address, 16 }, 00085 { hdr_data, 4 }, 00086 { (void *) data_ptr, data_length } 00087 }; 00088 00089 return ip_fcf_v(4, vec); 00090 }
Generated on Sun Jul 17 2022 08:25:24 by 1.7.2