Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ip_fsc.c Source File

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 }