mirror of https://github.com/ARMmbed/mbed-os.git
91 lines
3.1 KiB
C
91 lines
3.1 KiB
C
/*
|
|
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "nsconfig.h"
|
|
|
|
#include "randLIB.h"
|
|
#include "Service_Libs/fnv_hash/fnv_hash.h"
|
|
|
|
#include "ipv6_flow.h"
|
|
|
|
bool ipv6_flow_auto_label = true;
|
|
|
|
/* Flow label hash computation for RFC 6347, but using algorithm 8 as
|
|
* suggested by "Comparing Hash Function Algorithms for the IPv6 Flow Label"
|
|
* (Anderson, Brownlee, Carpenter 2012).
|
|
*/
|
|
|
|
static inline uint_fast24_t fold_32_to_flow(uint32_t val32)
|
|
{
|
|
uint_fast24_t flow = (uint_fast24_t)((val32 ^ (val32 >> 20)) & 0xFFFFF);
|
|
if (flow == 0) {
|
|
flow = 1;
|
|
}
|
|
return flow;
|
|
}
|
|
|
|
/* Compute a flow from the traditional (src-IP,dst-IP,proto,src-port,dst-port)
|
|
* 5-tuple. To be used when building our own IP headers from a transport module.
|
|
*/
|
|
uint_fast24_t ipv6_flow_5tuple(const uint8_t src_addr[static 16],
|
|
const uint8_t dst_addr[static 16],
|
|
uint8_t protocol,
|
|
uint16_t src_port,
|
|
uint16_t dst_port)
|
|
{
|
|
uint32_t hash;
|
|
const uint8_t bytes[] = { dst_port >> 8, dst_port, src_port >> 8, src_port, protocol };
|
|
|
|
/* Hash algorithms suggest starting with the low-order bytes, as they're
|
|
* most likely to vary, increasing potential dispersion. This means using
|
|
* the "reverse" function on the IP addresses, and we use the same reverse
|
|
* for the other 3 tuple members to re-use the code.
|
|
*/
|
|
hash = fnv_hash_1a_32_reverse_block(src_addr, 16);
|
|
hash = fnv_hash_1a_32_reverse_block_update(hash, dst_addr, 16);
|
|
hash = fnv_hash_1a_32_reverse_block_update(hash, bytes, sizeof bytes);
|
|
|
|
return fold_32_to_flow(hash);
|
|
}
|
|
|
|
/* Compute a flow from a basic (src-IP,dst-IP) 2-tuple, plus an existing flow
|
|
* label. To be used on tunnel entry, using fields from inner header.
|
|
*/
|
|
uint_fast24_t ipv6_flow_2tuple_flow(const uint8_t src_addr[static 16],
|
|
const uint8_t dst_addr[static 16],
|
|
uint_fast24_t flow)
|
|
{
|
|
uint32_t hash;
|
|
|
|
flow &= 0xFFFFF;
|
|
const uint8_t bytes[] = { flow >> 16, flow >> 8, flow };
|
|
|
|
hash = fnv_hash_1a_32_reverse_block(bytes, sizeof bytes);
|
|
hash = fnv_hash_1a_32_reverse_block_update(hash, src_addr, 16);
|
|
hash = fnv_hash_1a_32_reverse_block_update(hash, dst_addr, 16);
|
|
|
|
return fold_32_to_flow(hash);
|
|
}
|
|
|
|
/* Compute a random flow label. To be used on a connected socket. */
|
|
uint_fast24_t ipv6_flow_random(void)
|
|
{
|
|
uint32_t rand32 = randLIB_get_32bit();
|
|
|
|
return fold_32_to_flow(rand32);
|
|
}
|