Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ipv6_flow.c Source File

ipv6_flow.c

00001 /*
00002  * Copyright (c) 2016-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 
00018 #include "nsconfig.h"
00019 
00020 #include "randLIB.h"
00021 #include "Service_Libs/fnv_hash/fnv_hash.h"
00022 
00023 #include "ipv6_flow.h"
00024 
00025 bool ipv6_flow_auto_label = true;
00026 
00027 /* Flow label hash computation for RFC 6347, but using algorithm 8 as
00028  * suggested by "Comparing Hash Function Algorithms for the IPv6 Flow Label"
00029  * (Anderson, Brownlee, Carpenter 2012).
00030  */
00031 
00032 static inline uint_fast24_t fold_32_to_flow(uint32_t val32)
00033 {
00034     uint_fast24_t flow = (uint_fast24_t) ((val32 ^ (val32 >> 20)) & 0xFFFFF);
00035     if (flow == 0) {
00036         flow = 1;
00037     }
00038     return flow;
00039 }
00040 
00041 /* Compute a flow from the traditional (src-IP,dst-IP,proto,src-port,dst-port)
00042  * 5-tuple. To be used when building our own IP headers from a transport module.
00043  */
00044 uint_fast24_t ipv6_flow_5tuple(const uint8_t src_addr[static 16],
00045                                const uint8_t dst_addr[static 16],
00046                                uint8_t protocol,
00047                                uint16_t src_port,
00048                                uint16_t dst_port)
00049 {
00050     uint32_t hash;
00051     const uint8_t bytes[] = { dst_port >> 8, dst_port, src_port >> 8, src_port, protocol };
00052 
00053     /* Hash algorithms suggest starting with the low-order bytes, as they're
00054      * most likely to vary, increasing potential dispersion. This means using
00055      * the "reverse" function on the IP addresses, and we use the same reverse
00056      * for the other 3 tuple members to re-use the code.
00057      */
00058     hash = fnv_hash_1a_32_reverse_block(src_addr, 16);
00059     hash = fnv_hash_1a_32_reverse_block_update(hash, dst_addr, 16);
00060     hash = fnv_hash_1a_32_reverse_block_update(hash, bytes, sizeof bytes);
00061 
00062     return fold_32_to_flow(hash);
00063 }
00064 
00065 /* Compute a flow from a basic (src-IP,dst-IP) 2-tuple, plus an existing flow
00066  * label. To be used on tunnel entry, using fields from inner header.
00067  */
00068 uint_fast24_t ipv6_flow_2tuple_flow(const uint8_t src_addr[static 16],
00069                                     const uint8_t dst_addr[static 16],
00070                                     uint_fast24_t flow)
00071 {
00072     uint32_t hash;
00073 
00074     flow &= 0xFFFFF;
00075     const uint8_t bytes[] = { flow >> 16, flow >> 8, flow };
00076 
00077     hash = fnv_hash_1a_32_reverse_block(bytes, sizeof bytes);
00078     hash = fnv_hash_1a_32_reverse_block_update(hash, src_addr, 16);
00079     hash = fnv_hash_1a_32_reverse_block_update(hash, dst_addr, 16);
00080 
00081     return fold_32_to_flow(hash);
00082 }
00083 
00084 /* Compute a random flow label. To be used on a connected socket. */
00085 uint_fast24_t ipv6_flow_random(void)
00086 {
00087     uint32_t rand32 = randLIB_get_32bit();
00088 
00089     return fold_32_to_flow(rand32);
00090 }